* src/SDCCast.c (gatherAutoInit): allow pic16 to emit static
[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         pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
658         if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
659           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) {
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           sprintf(s,"%s", pcop->name);
1505         } else
1506           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1507
1508       }
1509       rs = Safe_calloc(1,strlen(s)+1);
1510       strcpy(rs,s);   
1511       return rs;
1512
1513     case AOP_STA:
1514         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1515         return (rs);
1516         
1517     case AOP_STK:
1518 //        pCodeOp *pcop = aop->aop
1519         break;
1520
1521     }
1522
1523     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1524     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1525            "aopget got unsupported aop->type");
1526     exit(0);
1527 }
1528
1529
1530
1531 /* lock has the following meaning: When allocating temporary registers
1532  * for stack variables storage, the value of the temporary register is
1533  * saved on stack. Its value is restored at the end. This procedure is
1534  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1535  * a possibility that before a call to pic16_aopOp, a temporary register
1536  * is allocated for a while and it is freed after some time, this will
1537  * mess the stack and values will not be restored properly. So use lock=1
1538  * to allocate temporary registers used internally by the programmer, and
1539  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1540  * to inform the compiler developer about a possible bug. This is an internal
1541  * feature for developing the compiler -- VR */
1542  
1543 int _TempReg_lock = 0;
1544 /*-----------------------------------------------------------------*/
1545 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1546 /*-----------------------------------------------------------------*/
1547 pCodeOp *pic16_popGetTempReg(int lock)
1548 {
1549   pCodeOp *pcop;
1550   symbol *cfunc;
1551
1552 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1553     if(_TempReg_lock) {
1554 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1555     }
1556     
1557     _TempReg_lock += lock;
1558     
1559     cfunc = currFunc;
1560     currFunc = NULL;
1561
1562     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1563     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1564       PCOR(pcop)->r->wasUsed=1;
1565       PCOR(pcop)->r->isFree=0;
1566
1567       /* push value on stack */
1568       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1569     }
1570
1571     currFunc = cfunc;
1572
1573   return pcop;
1574 }
1575
1576 /*-----------------------------------------------------------------*/
1577 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but   */
1578 /*                            don't save if inside v               */
1579 /*-----------------------------------------------------------------*/
1580 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1581 {
1582   pCodeOp *pcop;
1583   symbol *cfunc;
1584
1585 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1586
1587     if(_TempReg_lock) {
1588 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1589     }
1590
1591     _TempReg_lock += lock;
1592
1593     cfunc = currFunc;
1594     currFunc = NULL;
1595
1596     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1597     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1598       PCOR(pcop)->r->wasUsed=1;
1599       PCOR(pcop)->r->isFree=0;
1600
1601       if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1602       /* push value on stack */
1603         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1604       }
1605     }
1606
1607     currFunc = cfunc;
1608
1609   return pcop;
1610 }
1611
1612
1613 /*-----------------------------------------------------------------*/
1614 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1615 /*-----------------------------------------------------------------*/
1616 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1617 {
1618   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1619
1620   _TempReg_lock -= lock;
1621
1622   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1623     PCOR(pcop)->r->isFree = 1;
1624     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1625   }
1626 }
1627 /*-----------------------------------------------------------------*/
1628 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1629 /*-----------------------------------------------------------------*/
1630 pCodeOp *pic16_popGetLabel(unsigned int key)
1631 {
1632
1633   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1634
1635   if(key>max_key)
1636     max_key = key;
1637
1638   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1639 }
1640
1641 /*-----------------------------------------------------------------*/
1642 /* pic16_popCopyReg - copy a pcode operator                              */
1643 /*-----------------------------------------------------------------*/
1644 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1645 {
1646   pCodeOpReg *pcor;
1647
1648   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1649   pcor->pcop.type = pc->pcop.type;
1650   if(pc->pcop.name) {
1651     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1652       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1653   } else
1654     pcor->pcop.name = NULL;
1655
1656   pcor->r = pc->r;
1657   pcor->rIdx = pc->rIdx;
1658   pcor->r->wasUsed=1;
1659
1660 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1661
1662   return PCOP(pcor);
1663 }
1664
1665 /*-----------------------------------------------------------------*/
1666 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1667 /*-----------------------------------------------------------------*/
1668 pCodeOp *pic16_popGetLit(int lit)
1669 {
1670   return pic16_newpCodeOpLit(lit);
1671 }
1672
1673 /*-----------------------------------------------------------------*/
1674 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1675 /*-----------------------------------------------------------------*/
1676 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1677 {
1678   return pic16_newpCodeOpLit2(lit, arg2);
1679 }
1680
1681
1682 /*-----------------------------------------------------------------*/
1683 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1684 /*-----------------------------------------------------------------*/
1685 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1686 {
1687   return pic16_newpCodeOpImmd(name, offset,index, 0);
1688 }
1689
1690
1691 /*-----------------------------------------------------------------*/
1692 /* pic16_popGet - asm operator to pcode operator conversion              */
1693 /*-----------------------------------------------------------------*/
1694 pCodeOp *pic16_popGetWithString(char *str)
1695 {
1696   pCodeOp *pcop;
1697
1698
1699   if(!str) {
1700     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1701     exit (1);
1702   }
1703
1704   pcop = pic16_newpCodeOp(str,PO_STR);
1705
1706   return pcop;
1707 }
1708
1709 /*-----------------------------------------------------------------*/
1710 /* pic16_popRegFromString -                                        */
1711 /*-----------------------------------------------------------------*/
1712 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1713 {
1714
1715   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1716   pcop->type = PO_DIR;
1717
1718   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1719   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1720
1721   if(!str)
1722     str = "BAD_STRING";
1723
1724   pcop->name = Safe_calloc(1,strlen(str)+1);
1725   strcpy(pcop->name,str);
1726
1727   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1728
1729   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1730
1731   /* make sure that register doesn't exist,
1732    * and operand isn't NULL
1733    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1734   if((PCOR(pcop)->r == NULL) 
1735     && (op)
1736     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1737 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1738 //              __FUNCTION__, __LINE__, str, size, offset);
1739
1740     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1741     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1742
1743   }
1744   PCOR(pcop)->instance = offset;
1745
1746   return pcop;
1747 }
1748
1749 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1750 {
1751   pCodeOp *pcop;
1752
1753 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1754
1755         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1756         PCOR(pcop)->rIdx = rIdx;
1757         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1758
1759         PCOR(pcop)->r->isFree = 0;
1760         PCOR(pcop)->r->wasUsed = 1;
1761
1762         pcop->type = PCOR(pcop)->r->pc_type;
1763
1764   return pcop;
1765 }
1766
1767 /*---------------------------------------------------------------------------------*/
1768 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1769 /*                 VR 030601                                                       */
1770 /*---------------------------------------------------------------------------------*/
1771 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1772 {
1773   pCodeOpReg2 *pcop2;
1774   pCodeOp *temp;
1775   
1776         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1777
1778         /* comment the following check, so errors to throw up */
1779 //      if(!pcop2)return NULL;
1780
1781         temp = pic16_popGet(aop_dst, offset);
1782         pcop2->pcop2 = temp;
1783         
1784   return PCOP(pcop2);
1785 }
1786
1787
1788
1789 /*--------------------------------------------------------------------------------.-*/
1790 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1791 /*                  VR 030601 , adapted by Hans Dorn                                */
1792 /*--------------------------------------------------------------------------------.-*/
1793 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1794 {
1795   pCodeOpReg2 *pcop2;
1796  
1797         pcop2 = (pCodeOpReg2 *)src;
1798         pcop2->pcop2 = dst;
1799         
1800         return PCOP(pcop2);
1801 }
1802
1803
1804
1805 /*---------------------------------------------------------------------------------*/
1806 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1807 /*                     movff instruction                                           */
1808 /*---------------------------------------------------------------------------------*/
1809 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1810 {
1811   pCodeOpReg2 *pcop2;
1812
1813         if(!noalloc) {
1814                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1815                 pcop2->pcop2 = pic16_popCopyReg(dst);
1816         } else {
1817                 /* the pCodeOp may be already allocated */
1818                 pcop2 = (pCodeOpReg2 *)(src);
1819                 pcop2->pcop2 = (pCodeOp *)(dst);
1820         }
1821
1822   return PCOP(pcop2);
1823 }
1824
1825
1826 /*-----------------------------------------------------------------*/
1827 /* pic16_popGet - asm operator to pcode operator conversion              */
1828 /*-----------------------------------------------------------------*/
1829 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1830 {
1831   //char *s = buffer ;
1832   char *rs;
1833   pCodeOp *pcop;
1834
1835     FENTRY2;
1836     /* offset is greater than
1837     size then zero */
1838
1839 //    if (offset > (aop->size - 1) &&
1840 //        aop->type != AOP_LIT)
1841 //      return NULL;  //zero;
1842
1843     /* depending on type */
1844     switch (aop->type) {
1845         
1846     case AOP_R0:
1847     case AOP_R1:
1848     case AOP_DPTR:
1849     case AOP_DPTR2:
1850         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1851         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1852         assert( 0 );
1853         return NULL;
1854
1855
1856     case AOP_FSR0:
1857     case AOP_FSR2:
1858       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1859       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
1860       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1861       PCOR(pcop)->r->wasUsed = 1;
1862       PCOR(pcop)->r->isFree = 0;
1863       
1864       PCOR(pcop)->instance = offset;
1865       pcop->type = PCOR(pcop)->r->pc_type;
1866       return (pcop);
1867
1868     case AOP_IMMD:
1869       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1870       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1871
1872     case AOP_STA:
1873       /* pCodeOp is already allocated from aopForSym */
1874         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1875         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1876           
1877       return (pcop);
1878       
1879     case AOP_ACC:
1880       {
1881         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1882
1883         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1884
1885         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1886         
1887         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1888         PCOR(pcop)->rIdx = rIdx;
1889         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1890         PCOR(pcop)->r->wasUsed=1;
1891         PCOR(pcop)->r->isFree=0;
1892
1893         PCOR(pcop)->instance = offset;
1894         pcop->type = PCOR(pcop)->r->pc_type;
1895 //      rs = aop->aopu.aop_reg[offset]->name;
1896 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1897         return pcop;
1898
1899
1900 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1901 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1902
1903 //      assert( 0 );
1904       }
1905         
1906     case AOP_DIR:
1907       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1908       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1909         
1910     case AOP_REG:
1911       {
1912         int rIdx;
1913         assert (aop && aop->aopu.aop_reg[offset] != NULL);
1914         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1915
1916         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1917         
1918         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1919 //      pcop->type = PO_GPR_REGISTER;
1920         PCOR(pcop)->rIdx = rIdx;
1921         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
1922         PCOR(pcop)->r->wasUsed=1;
1923         PCOR(pcop)->r->isFree=0;
1924
1925         PCOR(pcop)->instance = offset;
1926         pcop->type = PCOR(pcop)->r->pc_type;
1927         
1928         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s\n", __LINE__, dumpPicOptype(pcop->type));
1929         rs = aop->aopu.aop_reg[offset]->name;
1930         DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1931         return pcop;
1932       }
1933
1934     case AOP_CRY:
1935         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1936
1937       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1938       PCOR(pcop)->instance = offset;
1939       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1940       //if(PCOR(pcop)->r == NULL)
1941       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1942       return pcop;
1943         
1944     case AOP_LIT:
1945         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1946       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1947
1948     case AOP_STR:
1949       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1950       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1951
1952       /*
1953       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1954       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1955       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1956       pcop->type = PCOR(pcop)->r->pc_type;
1957       pcop->name = PCOR(pcop)->r->name;
1958
1959       return pcop;
1960       */
1961
1962     case AOP_PCODE:
1963       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1964                           __LINE__, 
1965                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1966       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1967 #if 1
1968         switch( aop->aopu.pcop->type ) {
1969                 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1970                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1971                 default:
1972                         assert( 0 );    /* should never reach here */;
1973         }
1974 #else
1975       PCOI(pcop)->offset = offset;
1976 #endif
1977       return pcop;
1978     }
1979
1980     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1981            "pic16_popGet got unsupported aop->type");
1982     exit(0);
1983 }
1984 /*-----------------------------------------------------------------*/
1985 /* pic16_aopPut - puts a string for a aop                                */
1986 /*-----------------------------------------------------------------*/
1987 void pic16_aopPut (asmop *aop, char *s, int offset)
1988 {
1989     char *d = buffer ;
1990     symbol *lbl ;
1991
1992     return;
1993
1994     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1995
1996     if (aop->size && offset > ( aop->size - 1)) {
1997         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1998                "pic16_aopPut got offset > aop->size");
1999         exit(0);
2000     }
2001
2002     /* will assign value to value */
2003     /* depending on where it is ofcourse */
2004     switch (aop->type) {
2005     case AOP_DIR:
2006       if (offset) {
2007         sprintf(d,"(%s + %d)",
2008                 aop->aopu.aop_dir,offset);
2009         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2010
2011       } else
2012             sprintf(d,"%s",aop->aopu.aop_dir);
2013         
2014         if (strcmp(d,s)) {
2015           DEBUGpic16_emitcode(";","%d",__LINE__);
2016           if(strcmp(s,"W"))
2017             pic16_emitcode("movf","%s,w",s);
2018           pic16_emitcode("movwf","%s",d);
2019
2020           if(strcmp(s,"W")) {
2021             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2022             if(offset >= aop->size) {
2023               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2024               break;
2025             } else
2026               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2027           }
2028
2029           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2030
2031
2032         }
2033         break;
2034         
2035     case AOP_REG:
2036       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2037         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2038           /*
2039             if (*s == '@'           ||
2040                 strcmp(s,"r0") == 0 ||
2041                 strcmp(s,"r1") == 0 ||
2042                 strcmp(s,"r2") == 0 ||
2043                 strcmp(s,"r3") == 0 ||
2044                 strcmp(s,"r4") == 0 ||
2045                 strcmp(s,"r5") == 0 ||
2046                 strcmp(s,"r6") == 0 || 
2047                 strcmp(s,"r7") == 0 )
2048                 pic16_emitcode("mov","%s,%s  ; %d",
2049                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2050             else
2051           */
2052
2053           if(strcmp(s,"W")==0 )
2054             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2055
2056           pic16_emitcode("movwf","%s",
2057                    aop->aopu.aop_reg[offset]->name);
2058
2059           if(strcmp(s,zero)==0) {
2060             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2061
2062           } else if(strcmp(s,"W")==0) {
2063             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2064             pcop->type = PO_GPR_REGISTER;
2065
2066             PCOR(pcop)->rIdx = -1;
2067             PCOR(pcop)->r = NULL;
2068
2069             DEBUGpic16_emitcode(";","%d",__LINE__);
2070             pcop->name = Safe_strdup(s);
2071             pic16_emitpcode(POC_MOVFW,pcop);
2072             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2073           } else if(strcmp(s,one)==0) {
2074             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2075             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2076           } else {
2077             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2078           }
2079         }
2080         break;
2081         
2082     case AOP_DPTR:
2083     case AOP_DPTR2:
2084     
2085     if (aop->type == AOP_DPTR2)
2086     {
2087         genSetDPTR(1);
2088     }
2089     
2090         if (aop->code) {
2091             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2092                    "pic16_aopPut writting to code space");
2093             exit(0);
2094         }
2095         
2096         while (offset > aop->coff) {
2097             aop->coff++;
2098             pic16_emitcode ("inc","dptr");
2099         }
2100         
2101         while (offset < aop->coff) {
2102             aop->coff-- ;
2103             pic16_emitcode("lcall","__decdptr");
2104         }
2105         
2106         aop->coff = offset;
2107         
2108         /* if not in accumulater */
2109         MOVA(s);        
2110         
2111         pic16_emitcode ("movx","@dptr,a");
2112         
2113     if (aop->type == AOP_DPTR2)
2114     {
2115         genSetDPTR(0);
2116     }
2117         break;
2118         
2119     case AOP_R0:
2120     case AOP_R1:
2121         while (offset > aop->coff) {
2122             aop->coff++;
2123             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2124         }
2125         while (offset < aop->coff) {
2126             aop->coff-- ;
2127             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2128         }
2129         aop->coff = offset;
2130         
2131         if (aop->paged) {
2132             MOVA(s);           
2133             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2134             
2135         } else
2136             if (*s == '@') {
2137                 MOVA(s);
2138                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2139             } else
2140                 if (strcmp(s,"r0") == 0 ||
2141                     strcmp(s,"r1") == 0 ||
2142                     strcmp(s,"r2") == 0 ||
2143                     strcmp(s,"r3") == 0 ||
2144                     strcmp(s,"r4") == 0 ||
2145                     strcmp(s,"r5") == 0 ||
2146                     strcmp(s,"r6") == 0 || 
2147                     strcmp(s,"r7") == 0 ) {
2148                     char buffer[10];
2149                     sprintf(buffer,"a%s",s);
2150                     pic16_emitcode("mov","@%s,%s",
2151                              aop->aopu.aop_ptr->name,buffer);
2152                 } else
2153                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2154         
2155         break;
2156         
2157     case AOP_STK:
2158         if (strcmp(s,"a") == 0)
2159             pic16_emitcode("push","acc");
2160         else
2161             pic16_emitcode("push","%s",s);
2162         
2163         break;
2164         
2165     case AOP_CRY:
2166         /* if bit variable */
2167         if (!aop->aopu.aop_dir) {
2168             pic16_emitcode("clr","a");
2169             pic16_emitcode("rlc","a");
2170         } else {
2171             if (s == zero) 
2172                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2173             else
2174                 if (s == one)
2175                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2176                 else
2177                     if (!strcmp(s,"c"))
2178                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2179                     else {
2180                         lbl = newiTempLabel(NULL);
2181                         
2182                         if (strcmp(s,"a")) {
2183                             MOVA(s);
2184                         }
2185                         pic16_emitcode("clr","c");
2186                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2187                         pic16_emitcode("cpl","c");
2188                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2189                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2190                     }
2191         }
2192         break;
2193         
2194     case AOP_STR:
2195         aop->coff = offset;
2196         if (strcmp(aop->aopu.aop_str[offset],s))
2197             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2198         break;
2199         
2200     case AOP_ACC:
2201         aop->coff = offset;
2202         if (!offset && (strcmp(s,"acc") == 0))
2203             break;
2204         
2205         if (strcmp(aop->aopu.aop_str[offset],s))
2206             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2207         break;
2208
2209     default :
2210         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2211 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2212 //             "pic16_aopPut got unsupported aop->type");
2213 //      exit(0);    
2214     }    
2215
2216 }
2217
2218 /*-----------------------------------------------------------------*/
2219 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
2220 /*-----------------------------------------------------------------*/
2221 void mov2w (asmop *aop, int offset)
2222 {
2223   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2224
2225   if(is_LitAOp(aop))
2226     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2227   else
2228     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2229 }
2230
2231 static void mov2f(asmop *dst, asmop *src, int offset)
2232 {
2233   if(is_LitAOp(src)) {
2234     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2235     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2236   } else {
2237     if(pic16_sameRegsOfs(src, dst, offset))return;
2238     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2239                       pic16_popGet(dst, offset)));
2240   }
2241 }
2242
2243 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2244 {
2245   if(is_LitAOp(src)) {
2246     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2247     pic16_emitpcode(POC_MOVWF, dst);
2248   } else {
2249     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2250   }
2251 }
2252
2253 void pic16_testStackOverflow(void)
2254 {
2255 #define GSTACK_TEST_NAME        "__gstack_test"
2256
2257   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2258   
2259   {
2260     symbol *sym;
2261
2262       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2263       strcpy(sym->rname, GSTACK_TEST_NAME);
2264       checkAddSym(&externs, sym);
2265   }
2266
2267 }
2268
2269 /* push pcop into stack */
2270 void pic16_pushpCodeOp(pCodeOp *pcop)
2271 {
2272 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2273   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
2274   if(pic16_options.gstack)
2275     pic16_testStackOverflow();
2276     
2277 }
2278
2279 /* pop pcop from stack */
2280 void pic16_poppCodeOp(pCodeOp *pcop)
2281 {
2282   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
2283   if(pic16_options.gstack)
2284     pic16_testStackOverflow();
2285 }
2286
2287
2288 /*-----------------------------------------------------------------*/
2289 /* pushw - pushes wreg to stack                                    */
2290 /*-----------------------------------------------------------------*/
2291 void pushw(void)
2292 {
2293   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2294   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2295   if(pic16_options.gstack)
2296     pic16_testStackOverflow();
2297 }
2298
2299                 
2300 /*-----------------------------------------------------------------*/
2301 /* pushaop - pushes aop to stack                                   */
2302 /*-----------------------------------------------------------------*/
2303 void pushaop(asmop *aop, int offset)
2304 {
2305   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2306
2307   if(is_LitAOp(aop)) {
2308     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2309     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2310   } else {
2311     pic16_emitpcode(POC_MOVFF,
2312       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg(&pic16_pc_postdec1)));
2313   }
2314
2315 //  pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
2316   if(pic16_options.gstack)
2317     pic16_testStackOverflow();
2318 }
2319
2320 /*-----------------------------------------------------------------*/
2321 /* popaop - pops aop from stack                                    */
2322 /*-----------------------------------------------------------------*/
2323 void popaop(asmop *aop, int offset)
2324 {
2325   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2326   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
2327   if(pic16_options.gstack)
2328     pic16_testStackOverflow();
2329 }
2330
2331 void popaopidx(asmop *aop, int offset, int index)
2332 {
2333   int ofs=1;
2334
2335     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2336
2337     if(STACK_MODEL_LARGE)ofs++;
2338
2339     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2340     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
2341     if(pic16_options.gstack)
2342       pic16_testStackOverflow();
2343 }
2344
2345 /*-----------------------------------------------------------------*/
2346 /* reAdjustPreg - points a register back to where it should        */
2347 /*-----------------------------------------------------------------*/
2348 static void reAdjustPreg (asmop *aop)
2349 {
2350     int size ;
2351
2352     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2353     aop->coff = 0;
2354     if ((size = aop->size) <= 1)
2355         return ;
2356     size-- ;
2357     switch (aop->type) {
2358         case AOP_R0 :
2359         case AOP_R1 :
2360             while (size--)
2361                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2362             break;          
2363         case AOP_DPTR :
2364         case AOP_DPTR2:
2365             if (aop->type == AOP_DPTR2)
2366             {
2367                 genSetDPTR(1);
2368             } 
2369             while (size--)
2370             {
2371                 pic16_emitcode("lcall","__decdptr");
2372             }
2373                 
2374             if (aop->type == AOP_DPTR2)
2375             {
2376                 genSetDPTR(0);
2377             }                
2378             break;  
2379
2380     }   
2381
2382 }
2383
2384
2385 #if 0
2386 /*-----------------------------------------------------------------*/
2387 /* opIsGptr: returns non-zero if the passed operand is             */   
2388 /* a generic pointer type.                                         */
2389 /*-----------------------------------------------------------------*/ 
2390 static int opIsGptr(operand *op)
2391 {
2392     sym_link *type = operandType(op);
2393     
2394     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2395     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2396     {
2397         return 1;
2398     }
2399     return 0;        
2400 }
2401 #endif
2402
2403 /*-----------------------------------------------------------------*/
2404 /* pic16_getDataSize - get the operand data size                         */
2405 /*-----------------------------------------------------------------*/
2406 int pic16_getDataSize(operand *op)
2407 {
2408     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2409
2410
2411     return AOP_SIZE(op);
2412
2413     // tsd- in the pic port, the genptr size is 1, so this code here
2414     // fails. ( in the 8051 port, the size was 4).
2415 #if 0
2416     int size;
2417     size = AOP_SIZE(op);
2418     if (size == GPTRSIZE)
2419     {
2420         sym_link *type = operandType(op);
2421         if (IS_GENPTR(type))
2422         {
2423             /* generic pointer; arithmetic operations
2424              * should ignore the high byte (pointer type).
2425              */
2426             size--;
2427     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2428         }
2429     }
2430     return size;
2431 #endif
2432 }
2433
2434 /*-----------------------------------------------------------------*/
2435 /* pic16_outAcc - output Acc                                             */
2436 /*-----------------------------------------------------------------*/
2437 void pic16_outAcc(operand *result)
2438 {
2439   int size,offset;
2440   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2441   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2442
2443
2444   size = pic16_getDataSize(result);
2445   if(size){
2446     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2447     size--;
2448     offset = 1;
2449     /* unsigned or positive */
2450     while(size--)
2451       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2452   }
2453
2454 }
2455
2456 /*-----------------------------------------------------------------*/
2457 /* pic16_outBitC - output a bit C                                  */
2458 /*                 Move to result the value of Carry flag -- VR    */
2459 /*-----------------------------------------------------------------*/
2460 void pic16_outBitC(operand *result)
2461 {
2462   int i;
2463
2464     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2465
2466     /* if the result is bit */
2467     if (AOP_TYPE(result) == AOP_CRY) {
2468         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2469         pic16_aopPut(AOP(result),"c",0);
2470     } else {
2471
2472         i = AOP_SIZE(result);
2473         while(i--) {
2474                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2475         }
2476         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2477     }
2478 }
2479
2480 /*-----------------------------------------------------------------*/
2481 /* pic16_outBitOp - output a bit from Op                           */
2482 /*                 Move to result the value of set/clr op -- VR    */
2483 /*-----------------------------------------------------------------*/
2484 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2485 {
2486   int i;
2487
2488     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2489
2490     /* if the result is bit */
2491     if (AOP_TYPE(result) == AOP_CRY) {
2492         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2493         pic16_aopPut(AOP(result),"c",0);
2494     } else {
2495
2496         i = AOP_SIZE(result);
2497         while(i--) {
2498                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2499         }
2500         pic16_emitpcode(POC_RRCF, pcop);          
2501         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2502     }
2503 }
2504
2505 /*-----------------------------------------------------------------*/
2506 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2507 /*-----------------------------------------------------------------*/
2508 void pic16_toBoolean(operand *oper)
2509 {
2510     int size = AOP_SIZE(oper) - 1;
2511     int offset = 1;
2512
2513     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2514
2515     if ( AOP_TYPE(oper) != AOP_ACC) {
2516       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2517     }
2518     while (size--) {
2519       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2520     }
2521 }
2522
2523
2524 #if !defined(GEN_Not)
2525 /*-----------------------------------------------------------------*/
2526 /* genNot - generate code for ! operation                          */
2527 /*-----------------------------------------------------------------*/
2528 static void pic16_genNot (iCode *ic)
2529 {
2530   symbol *tlbl;
2531   int size;
2532
2533   FENTRY;
2534   /* assign asmOps to operand & result */
2535   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2536   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2537
2538   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2539   /* if in bit space then a special case */
2540   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2541     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2542       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2543       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2544     } else {
2545       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2546       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2547       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2548     }
2549     goto release;
2550   }
2551
2552   size = AOP_SIZE(IC_LEFT(ic));
2553   if(size == 1) {
2554     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2555     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2556     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2557     goto release;
2558   }
2559   pic16_toBoolean(IC_LEFT(ic));
2560
2561   tlbl = newiTempLabel(NULL);
2562   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2563   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2564   pic16_outBitC(IC_RESULT(ic));
2565
2566  release:    
2567   /* release the aops */
2568   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2569   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2570 }
2571 #endif
2572
2573
2574 #if !defined(GEN_Cpl)
2575 /*-----------------------------------------------------------------*/
2576 /* genCpl - generate code for complement                           */
2577 /*-----------------------------------------------------------------*/
2578 static void pic16_genCpl (iCode *ic)
2579 {
2580   int offset = 0;
2581   int size ;
2582
2583     FENTRY;
2584     /* assign asmOps to operand & result */
2585     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2586     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2587
2588     /* if both are in bit space then 
2589     a special case */
2590     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2591         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2592
2593         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2594         pic16_emitcode("cpl","c"); 
2595         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2596         goto release; 
2597     } 
2598
2599     size = AOP_SIZE(IC_RESULT(ic));
2600     while (size--) {
2601 /*
2602         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2603         MOVA(l);       
2604         pic16_emitcode("cpl","a");
2605         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2606 */
2607         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2608               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2609         } else {
2610                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2611                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2612         }
2613         offset++;
2614
2615     }
2616
2617
2618 release:
2619     /* release the aops */
2620     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2621     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2622 }
2623 #endif
2624
2625 /*-----------------------------------------------------------------*/
2626 /* genUminusFloat - unary minus for floating points                */
2627 /*-----------------------------------------------------------------*/
2628 static void genUminusFloat(operand *op,operand *result)
2629 {
2630   int size ,offset =0 ;
2631   
2632     FENTRY;
2633     /* for this we just need to flip the 
2634     first it then copy the rest in place */
2635     size = AOP_SIZE(op);
2636
2637     while(size--) {
2638       mov2f(AOP(result), AOP(op), offset);
2639       offset++;
2640     }
2641     
2642     /* toggle the MSB's highest bit */
2643     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2644 }
2645
2646 /*-----------------------------------------------------------------*/
2647 /* genUminus - unary minus code generation                         */
2648 /*-----------------------------------------------------------------*/
2649 static void genUminus (iCode *ic)
2650 {
2651   int size, i;
2652   sym_link *optype, *rtype;
2653
2654     FENTRY;     
2655     
2656     /* assign asmops */
2657     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2658     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2659
2660     /* if both in bit space then special case */
2661     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2662       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2663         
2664         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2665         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2666         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2667         goto release; 
2668     } 
2669
2670     optype = operandType(IC_LEFT(ic));
2671     rtype = operandType(IC_RESULT(ic));
2672
2673     /* if float then do float stuff */
2674     if (IS_FLOAT(optype)) {
2675       genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2676       goto release;
2677     }
2678
2679     /* otherwise subtract from zero by taking the 2's complement */
2680     size = AOP_SIZE(IC_LEFT(ic));
2681
2682     for(i=0; i<size; i++) {
2683       if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2684         pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2685       else {
2686         pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2687         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2688       }
2689     }
2690
2691     pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2692     for(i=1; i<size; i++) {
2693       emitSKPNZ;
2694       pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2695     }
2696
2697 release:
2698     /* release the aops */
2699     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2700     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2701 }
2702
2703 #if 0
2704 /*-----------------------------------------------------------------*/
2705 /* saveRegisters - will look for a call and save the registers     */
2706 /*-----------------------------------------------------------------*/
2707 static void saveRegisters(iCode *lic) 
2708 {
2709     int i;
2710     iCode *ic;
2711     bitVect *rsave;
2712     sym_link *dtype;
2713
2714     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2715     /* look for call */
2716     for (ic = lic ; ic ; ic = ic->next) 
2717         if (ic->op == CALL || ic->op == PCALL)
2718             break;
2719
2720     if (!ic) {
2721         fprintf(stderr,"found parameter push with no function call\n");
2722         return ;
2723     }
2724
2725     /* if the registers have been saved already then
2726     do nothing */
2727     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2728         return ;
2729
2730     /* find the registers in use at this time 
2731     and push them away to safety */
2732     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2733                           ic->rUsed);
2734
2735     ic->regsSaved = 1;
2736     if (options.useXstack) {
2737         if (bitVectBitValue(rsave,R0_IDX))
2738             pic16_emitcode("mov","b,r0");
2739         pic16_emitcode("mov","r0,%s",spname);
2740         for (i = 0 ; i < pic16_nRegs ; i++) {
2741             if (bitVectBitValue(rsave,i)) {
2742                 if (i == R0_IDX)
2743                     pic16_emitcode("mov","a,b");
2744                 else
2745                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2746                 pic16_emitcode("movx","@r0,a");
2747                 pic16_emitcode("inc","r0");
2748             }
2749         }
2750         pic16_emitcode("mov","%s,r0",spname);
2751         if (bitVectBitValue(rsave,R0_IDX))
2752             pic16_emitcode("mov","r0,b");           
2753     }// else
2754     //for (i = 0 ; i < pic16_nRegs ; i++) {
2755     //    if (bitVectBitValue(rsave,i))
2756     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2757     //}
2758
2759     dtype = operandType(IC_LEFT(ic));
2760     if (currFunc && dtype && 
2761         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2762         IFFUNC_ISISR(currFunc->type) &&
2763         !ic->bankSaved) 
2764
2765         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2766
2767 }
2768 /*-----------------------------------------------------------------*/
2769 /* unsaveRegisters - pop the pushed registers                      */
2770 /*-----------------------------------------------------------------*/
2771 static void unsaveRegisters (iCode *ic)
2772 {
2773     int i;
2774     bitVect *rsave;
2775
2776     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2777     /* find the registers in use at this time 
2778     and push them away to safety */
2779     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2780                           ic->rUsed);
2781     
2782     if (options.useXstack) {
2783         pic16_emitcode("mov","r0,%s",spname);   
2784         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2785             if (bitVectBitValue(rsave,i)) {
2786                 pic16_emitcode("dec","r0");
2787                 pic16_emitcode("movx","a,@r0");
2788                 if (i == R0_IDX)
2789                     pic16_emitcode("mov","b,a");
2790                 else
2791                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2792             }       
2793
2794         }
2795         pic16_emitcode("mov","%s,r0",spname);
2796         if (bitVectBitValue(rsave,R0_IDX))
2797             pic16_emitcode("mov","r0,b");
2798     } //else
2799     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2800     //    if (bitVectBitValue(rsave,i))
2801     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2802     //}
2803
2804 }  
2805 #endif
2806
2807 #if 0  // patch 14
2808 /*-----------------------------------------------------------------*/
2809 /* pushSide -                                                      */
2810 /*-----------------------------------------------------------------*/
2811 static void pushSide(operand * oper, int size)
2812 {
2813         int offset = 0;
2814     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2815         while (size--) {
2816                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2817                 if (AOP_TYPE(oper) != AOP_REG &&
2818                     AOP_TYPE(oper) != AOP_DIR &&
2819                     strcmp(l,"a") ) {
2820                         pic16_emitcode("mov","a,%s",l);
2821                         pic16_emitcode("push","acc");
2822                 } else
2823                         pic16_emitcode("push","%s",l);
2824         }
2825 }
2826 #endif // patch 14
2827
2828 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2829 {
2830   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2831     pic16_emitpcode(POC_MOVFW, src);
2832     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2833   } else {
2834     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2835         src, pic16_popGet(AOP(op), offset)));
2836   }
2837 }
2838
2839
2840 /*-----------------------------------------------------------------*/
2841 /* assignResultValue - assign results to oper, rescall==1 is       */
2842 /*                     called from genCall() or genPcall()         */
2843 /*-----------------------------------------------------------------*/
2844 static void assignResultValue(operand * oper, int rescall)
2845 {
2846   int size = AOP_SIZE(oper);
2847   int offset=0;
2848   
2849     FENTRY2;
2850 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2851     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2852
2853     if(rescall) {
2854       /* assign result from a call/pcall function() */
2855                 
2856       /* function results are stored in a special order,
2857        * see top of file with Function return policy, or manual */
2858
2859       if(size <= 4) {
2860         /* 8-bits, result in WREG */
2861         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2862                         
2863         if(size>1) {
2864           /* 16-bits, result in PRODL:WREG */
2865           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2866         }
2867                         
2868         if(size>2) {
2869           /* 24-bits, result in PRODH:PRODL:WREG */
2870           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2871         }
2872                         
2873         if(size>3) {
2874           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2875           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2876         }
2877       
2878       } else {
2879         /* >32-bits, result on stack, and FSR0 points to beginning.
2880          * Fix stack when done */
2881         /* FIXME FIXME */
2882 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2883         while (size--) {
2884 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2885 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2886                 
2887           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2888           GpsuedoStkPtr++;
2889         }
2890                         
2891         /* fix stack */
2892         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2893         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2894         if(STACK_MODEL_LARGE) {
2895           emitSKPNC;
2896           pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2897         }
2898       }                 
2899     } else {
2900       int areg = 0;             /* matching argument register */
2901       
2902 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2903       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2904
2905
2906       /* its called from genReceive (probably) -- VR */
2907       /* I hope this code will not be called from somewhere else in the future! 
2908        * We manually set the pseudo stack pointer in genReceive. - dw
2909        */
2910       if(!GpsuedoStkPtr && _G.useWreg) {
2911 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2912
2913         /* The last byte in the assignment is in W */
2914         if(areg <= GpsuedoStkPtr) {
2915           size--;
2916           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2917           offset++;
2918 //          debugf("receive from WREG\n", 0);
2919         }
2920         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
2921       }
2922 //      GpsuedoStkPtr++;
2923       _G.stack_lat = AOP_SIZE(oper)-1;
2924
2925       while (size) {
2926         size--;
2927         GpsuedoStkPtr++;
2928         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
2929 //        debugf("receive from STACK\n", 0);
2930         offset++;
2931       }
2932     }
2933 }
2934
2935
2936 /*-----------------------------------------------------------------*/
2937 /* genIpush - generate code for pushing this gets a little complex */
2938 /*-----------------------------------------------------------------*/
2939 static void genIpush (iCode *ic)
2940 {
2941 //  int size, offset=0;
2942
2943   FENTRY;
2944   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2945
2946   if(ic->parmPush) {
2947     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2948
2949     /* send to stack as normal */
2950     addSet(&_G.sendSet,ic);
2951 //    addSetHead(&_G.sendSet,ic);
2952     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2953   }
2954
2955         
2956 #if 0
2957     int size, offset = 0 ;
2958     char *l;
2959
2960
2961     /* if this is not a parm push : ie. it is spill push 
2962     and spill push is always done on the local stack */
2963     if (!ic->parmPush) {
2964
2965         /* and the item is spilt then do nothing */
2966         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2967             return ;
2968
2969         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2970         size = AOP_SIZE(IC_LEFT(ic));
2971         /* push it on the stack */
2972         while(size--) {
2973             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2974             if (*l == '#') {
2975                 MOVA(l);
2976                 l = "acc";
2977             }
2978             pic16_emitcode("push","%s",l);
2979         }
2980         return ;        
2981     }
2982
2983     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2984 #endif
2985 }
2986
2987 /*-----------------------------------------------------------------*/
2988 /* genIpop - recover the registers: can happen only for spilling   */
2989 /*-----------------------------------------------------------------*/
2990 static void genIpop (iCode *ic)
2991 {
2992   FENTRY;
2993   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2994 #if 0
2995     int size,offset ;
2996
2997
2998     /* if the temp was not pushed then */
2999     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3000         return ;
3001
3002     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3003     size = AOP_SIZE(IC_LEFT(ic));
3004     offset = (size-1);
3005     while (size--) 
3006         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3007                                    FALSE,TRUE));
3008
3009     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3010 #endif
3011 }
3012
3013 #if 0
3014 /*-----------------------------------------------------------------*/
3015 /* unsaverbank - restores the resgister bank from stack            */
3016 /*-----------------------------------------------------------------*/
3017 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3018 {
3019   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3020 #if 0
3021     int i;
3022     asmop *aop ;
3023     regs *r = NULL;
3024
3025     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3026     if (popPsw) {
3027         if (options.useXstack) {
3028             aop = newAsmop(0);
3029             r = getFreePtr(ic,&aop,FALSE);
3030             
3031             
3032             pic16_emitcode("mov","%s,_spx",r->name);
3033             pic16_emitcode("movx","a,@%s",r->name);
3034             pic16_emitcode("mov","psw,a");
3035             pic16_emitcode("dec","%s",r->name);
3036             
3037         }else
3038             pic16_emitcode ("pop","psw");
3039     }
3040
3041     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3042         if (options.useXstack) {       
3043             pic16_emitcode("movx","a,@%s",r->name);
3044             //pic16_emitcode("mov","(%s+%d),a",
3045             //       regspic16[i].base,8*bank+regspic16[i].offset);
3046             pic16_emitcode("dec","%s",r->name);
3047
3048         } else 
3049           pic16_emitcode("pop",""); //"(%s+%d)",
3050         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3051     }
3052
3053     if (options.useXstack) {
3054
3055         pic16_emitcode("mov","_spx,%s",r->name);
3056         pic16_freeAsmop(NULL,aop,ic,TRUE);
3057
3058     }
3059 #endif 
3060 }
3061
3062 /*-----------------------------------------------------------------*/
3063 /* saverbank - saves an entire register bank on the stack          */
3064 /*-----------------------------------------------------------------*/
3065 static void saverbank (int bank, iCode *ic, bool pushPsw)
3066 {
3067   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3068 #if 0
3069     int i;
3070     asmop *aop ;
3071     regs *r = NULL;
3072
3073     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3074     if (options.useXstack) {
3075
3076         aop = newAsmop(0);
3077         r = getFreePtr(ic,&aop,FALSE);  
3078         pic16_emitcode("mov","%s,_spx",r->name);
3079
3080     }
3081
3082     for (i = 0 ; i < pic16_nRegs ;i++) {
3083         if (options.useXstack) {
3084             pic16_emitcode("inc","%s",r->name);
3085             //pic16_emitcode("mov","a,(%s+%d)",
3086             //         regspic16[i].base,8*bank+regspic16[i].offset);
3087             pic16_emitcode("movx","@%s,a",r->name);           
3088         } else 
3089           pic16_emitcode("push","");// "(%s+%d)",
3090                      //regspic16[i].base,8*bank+regspic16[i].offset);
3091     }
3092     
3093     if (pushPsw) {
3094         if (options.useXstack) {
3095             pic16_emitcode("mov","a,psw");
3096             pic16_emitcode("movx","@%s,a",r->name);     
3097             pic16_emitcode("inc","%s",r->name);
3098             pic16_emitcode("mov","_spx,%s",r->name);       
3099             pic16_freeAsmop (NULL,aop,ic,TRUE);
3100             
3101         } else
3102             pic16_emitcode("push","psw");
3103         
3104         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3105     }
3106     ic->bankSaved = 1;
3107 #endif
3108 }
3109 #endif  /* 0 */
3110
3111
3112 static int wparamCmp(void *p1, void *p2)
3113 {
3114   return (!strcmp((char *)p1, (char *)p2));
3115 }
3116
3117 int inWparamList(char *s)
3118 {
3119   return isinSetWith(wparamList, s, wparamCmp);
3120
3121
3122
3123 /*-----------------------------------------------------------------*/
3124 /* genCall - generates a call statement                            */
3125 /*-----------------------------------------------------------------*/
3126 static void genCall (iCode *ic)
3127 {
3128   sym_link *ftype;   
3129   int stackParms=0;
3130   int use_wreg=0;
3131   int inwparam=0;
3132   char *fname;
3133   
3134     FENTRY;
3135
3136     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3137     /* if caller saves & we have not saved then */
3138 //    if (!ic->regsSaved)
3139 //      saveRegisters(ic);
3140
3141         /* initialise stackParms for IPUSH pushes */
3142 //      stackParms = psuedoStkPtr;
3143 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3144     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3145     inwparam = inWparamList(OP_SYMBOL(IC_LEFT(ic))->name);
3146
3147 #if 0
3148     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3149 #endif
3150
3151     /* if send set is not empty the assign */
3152     if (_G.sendSet) {
3153       iCode *sic;
3154       int psuedoStkPtr=-1; 
3155       int firstTimeThruLoop = 1;
3156
3157
3158         /* reverse sendSet if function is not reentrant */
3159         if(!IFFUNC_ISREENT(ftype))
3160           _G.sendSet = reverseSet(_G.sendSet);
3161
3162         /* First figure how many parameters are getting passed */
3163         stackParms = 0;
3164         use_wreg = 0;
3165         
3166         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3167           int size;
3168 //          int offset = 0;
3169
3170             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3171             size = AOP_SIZE(IC_LEFT(sic));
3172
3173             stackParms += size;
3174
3175             /* pass the last byte through WREG */
3176             if(inwparam) {
3177
3178               while (size--) {
3179                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3180                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3181                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3182
3183                 if(!firstTimeThruLoop) {
3184                   /* If this is not the first time we've been through the loop
3185                    * then we need to save the parameter in a temporary
3186                    * register. The last byte of the last parameter is
3187                    * passed in W. */
3188
3189                   pushw();
3190 //                  --psuedoStkPtr;             // sanity check
3191                   use_wreg = 1;
3192                 }
3193                 
3194                 firstTimeThruLoop=0;
3195
3196                 mov2w (AOP(IC_LEFT(sic)), size);
3197
3198 //                offset++;
3199               }
3200             } else {
3201               /* all arguments are passed via stack */
3202               use_wreg = 0;
3203
3204               while (size--) {
3205                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3206                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3207                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3208
3209 //                pushaop(AOP(IC_LEFT(sic)), size);
3210                 mov2w (AOP(IC_LEFT(sic)), size);
3211                 pushw();
3212               }
3213             }
3214
3215             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3216           }
3217
3218           if(inwparam) {
3219             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3220               pushw();  /* save last parameter to stack if functions has varargs */
3221               use_wreg = 0;
3222             } else
3223               use_wreg = 1;
3224           } else use_wreg = 0;
3225
3226           _G.stackRegSet = _G.sendSet;
3227           _G.sendSet = NULL;
3228     }
3229
3230     /* make the call */
3231     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3232
3233     GpsuedoStkPtr=0;
3234     
3235     /* if we need to assign a result value */
3236     if ((IS_ITEMP(IC_RESULT(ic))
3237           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3238               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3239         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3240
3241       _G.accInUse++;
3242       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3243       _G.accInUse--;
3244
3245       assignResultValue(IC_RESULT(ic), 1);
3246
3247       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3248                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3249                 
3250       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3251     }
3252
3253     if(!stackParms && ic->parmBytes) {
3254       stackParms = ic->parmBytes;
3255     }
3256       
3257     stackParms -= use_wreg;
3258     
3259     if(stackParms>0) {
3260       if(stackParms == 1) {
3261         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1l));
3262       } else {
3263         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3264         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3265       }
3266       if(STACK_MODEL_LARGE) {
3267         emitSKPNC;
3268         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3269       }
3270     }
3271
3272 #if 0
3273     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3274 #endif
3275
3276     /* adjust the stack for parameters if required */
3277 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3278
3279 #if 0
3280       /* if register bank was saved then pop them */
3281       if (ic->bankSaved)
3282         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3283
3284       /* if we hade saved some registers then unsave them */
3285       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3286         unsaveRegisters (ic);
3287 #endif
3288 }
3289
3290
3291
3292 /*-----------------------------------------------------------------*/
3293 /* genPcall - generates a call by pointer statement                */
3294 /*            new version, created from genCall - HJD              */
3295 /*-----------------------------------------------------------------*/
3296 static void genPcall (iCode *ic)
3297 {
3298   sym_link *ftype, *fntype;
3299   int stackParms=0;
3300   symbol *retlbl = newiTempLabel(NULL);
3301   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3302   
3303     FENTRY;
3304
3305     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3306     fntype = operandType( IC_LEFT(ic) )->next;
3307
3308     /* if send set is not empty the assign */
3309     if (_G.sendSet) {
3310       iCode *sic;
3311       int psuedoStkPtr=-1; 
3312
3313       /* reverse sendSet if function is not reentrant */
3314       if(!IFFUNC_ISREENT(fntype))
3315         _G.sendSet = reverseSet(_G.sendSet);
3316
3317       stackParms = 0;
3318       
3319       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3320         int size;
3321
3322           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3323           size = AOP_SIZE(IC_LEFT(sic));
3324           stackParms += size;
3325
3326           /* all parameters are passed via stack, since WREG is clobbered
3327            * by the calling sequence */
3328           while (size--) {
3329             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3330             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3331             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3332
3333             mov2w (AOP(IC_LEFT(sic)), size);
3334             pushw();
3335           }
3336
3337           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3338       }
3339
3340       _G.stackRegSet = _G.sendSet;
3341       _G.sendSet = NULL;
3342     }
3343
3344     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3345
3346     // push return address
3347     // push $ on return stack, then replace with retlbl
3348
3349     pic16_emitpcodeNULLop(POC_PUSH);
3350
3351     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3352     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3353     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3354     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3355     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3356     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3357
3358     /* make the call by writing the pointer into pc */
3359     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3360     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3361
3362     // note: MOVFF to PCL not allowed
3363     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3364     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3365
3366
3367     /* return address is here: (X) */
3368     pic16_emitpLabelFORCE(retlbl->key);
3369
3370     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3371
3372     GpsuedoStkPtr=0;
3373     /* if we need assign a result value */
3374     if ((IS_ITEMP(IC_RESULT(ic))
3375           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3376               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3377         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3378
3379       _G.accInUse++;
3380       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3381       _G.accInUse--;
3382
3383       assignResultValue(IC_RESULT(ic), 1);
3384
3385       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3386               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3387                 
3388       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3389     }
3390
3391 //    stackParms -= use_wreg;
3392     
3393     if(stackParms>0) {
3394       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3395       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3396       if(STACK_MODEL_LARGE) {
3397         /* this implies that stackParms < 256 !!! -- VR */
3398         emitSKPNC;
3399         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3400       }
3401     }
3402 }
3403
3404 /*-----------------------------------------------------------------*/
3405 /* resultRemat - result  is rematerializable                       */
3406 /*-----------------------------------------------------------------*/
3407 static int resultRemat (iCode *ic)
3408 {
3409   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3410   if (SKIP_IC(ic) || ic->op == IFX)
3411     return 0;
3412
3413   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3414     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3415     if (sym->remat && !POINTER_SET(ic)) 
3416       return 1;
3417   }
3418
3419   return 0;
3420 }
3421
3422 #if defined(__BORLANDC__) || defined(_MSC_VER)
3423 #define STRCASECMP stricmp
3424 #else
3425 #define STRCASECMP strcasecmp
3426 #endif
3427
3428 #if 0
3429 /*-----------------------------------------------------------------*/
3430 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3431 /*-----------------------------------------------------------------*/
3432 static bool inExcludeList(char *s)
3433 {
3434   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3435     int i =0;
3436     
3437     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3438     if (options.excludeRegs[i] &&
3439     STRCASECMP(options.excludeRegs[i],"none") == 0)
3440         return FALSE ;
3441
3442     for ( i = 0 ; options.excludeRegs[i]; i++) {
3443         if (options.excludeRegs[i] &&
3444         STRCASECMP(s,options.excludeRegs[i]) == 0)
3445             return TRUE;
3446     }
3447     return FALSE ;
3448 }
3449 #endif
3450
3451 /*-----------------------------------------------------------------*/
3452 /* genFunction - generated code for function entry                 */
3453 /*-----------------------------------------------------------------*/
3454 static void genFunction (iCode *ic)
3455 {
3456   symbol *sym;
3457   sym_link *ftype;
3458   
3459     FENTRY;
3460     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3461
3462     pic16_labelOffset += (max_key+4);
3463     max_key=0;
3464     GpsuedoStkPtr=0;
3465     _G.nRegsSaved = 0;
3466         
3467     ftype = operandType(IC_LEFT(ic));
3468     sym = OP_SYMBOL(IC_LEFT(ic));
3469
3470     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3471       /* create an absolute section at the interrupt vector:
3472        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3473       symbol *asym;
3474       char asymname[128];
3475       pBlock *apb;
3476
3477         {
3478           int i, found=-1;
3479
3480             sym = OP_SYMBOL( IC_LEFT(ic));
3481             for(i=0;i<=2;i++) {
3482               if(interrupts[i]->name
3483                     && !STRCASECMP(interrupts[i]->name, sym->name)) {
3484                   found = i;
3485                   break;
3486               }
3487             }
3488                         
3489             if(found == -1) {
3490               fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3491                             __FILE__, __LINE__, sym->name);
3492               assert( 0 );
3493             }
3494             _G.interruptvector = found;
3495         }
3496
3497         sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3498         asym = newSymbol(asymname, 0);
3499
3500         apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3501         pic16_addpBlock( apb );
3502
3503         pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3504         pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3505         pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3506                 
3507         /* mark the end of this tiny function */
3508         pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3509
3510         {
3511           absSym *abSym;
3512
3513             abSym = Safe_calloc(1, sizeof(absSym));
3514             strcpy(abSym->name, asymname);
3515
3516             switch( _G.interruptvector ) {
3517               case 0: abSym->address = 0x000000; break;
3518               case 1: abSym->address = 0x000008; break;
3519               case 2: abSym->address = 0x000018; break;
3520             }
3521
3522             /* relocate interrupt vectors if needed */
3523             abSym->address += pic16_options.ivt_loc;
3524
3525             addSet(&absSymSet, abSym);
3526         }
3527     }
3528
3529     /* create the function header */
3530     pic16_emitcode(";","-----------------------------------------");
3531     pic16_emitcode(";"," function %s",sym->name);
3532     pic16_emitcode(";","-----------------------------------------");
3533
3534     pic16_emitcode("","%s:",sym->rname);
3535     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3536
3537
3538     {
3539       absSym *ab;
3540
3541         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3542           if(!strcmp(ab->name, sym->rname)) {
3543             pic16_pBlockConvert2Absolute(pb);
3544             break;
3545           }
3546         }
3547     }
3548
3549
3550     if(IFFUNC_ISNAKED(ftype)) {
3551       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3552       return;
3553     }
3554         
3555     /* if critical function then turn interrupts off */
3556     if (IFFUNC_ISCRITICAL(ftype)) {
3557       //pic16_emitcode("clr","ea");
3558     }
3559
3560     _G.fregsUsed = sym->regsUsed;
3561
3562     /* if this is an interrupt service routine then
3563      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3564     if (IFFUNC_ISISR(sym->type)) {
3565         _G.usefastretfie = 1;   /* use shadow registers by default */
3566         
3567         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3568         if(!(_G.interruptvector == 1)) {
3569           /* do not save WREG,STATUS,BSR for high priority interrupts
3570            * because they are stored in the hardware shadow registers already */
3571           _G.usefastretfie = 0;
3572           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3573           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3574           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3575         }
3576
3577         /* these should really be optimized somehow, because not all
3578          * interrupt handlers modify them */
3579         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3580         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3581         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3582         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3583         
3584 //        pic16_pBlockConvert2ISR(pb);
3585                 
3586     }
3587
3588     /* emit code to setup stack frame if user enabled,
3589      * and function is not main() */
3590          
3591     //fprintf(stderr, "function name: %s\n", sym->name);
3592     if(strcmp(sym->name, "main")) {
3593       if(1  /*!options.ommitFramePtr || sym->regsUsed*/) {
3594         /* setup the stack frame */
3595         if(STACK_MODEL_LARGE)
3596           pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2h));
3597         pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2l));
3598 //        pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3599         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3600         if(STACK_MODEL_LARGE)
3601           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3602       }
3603     }
3604
3605     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3606           && sym->stack) {
3607
3608       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3609
3610       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3611       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_fsr1l));
3612       emitSKPC;
3613       pic16_emitpcode(POC_DECF, pic16_popCopyReg(&pic16_pc_fsr1h));
3614     }
3615           
3616     if(inWparamList(sym->name)) {
3617       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3618         _G.useWreg = 0;
3619       else
3620         _G.useWreg = 1;
3621     } else
3622       _G.useWreg = 0;
3623
3624     /* if callee-save to be used for this function
3625      * then save the registers being used in this function */
3626 //    if (IFFUNC_CALLEESAVES(sym->type))
3627     {
3628       int i;
3629
3630         /* if any registers used */
3631         if (sym->regsUsed) {
3632           /* save the registers used */
3633           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3634           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3635           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3636             if (bitVectBitValue(sym->regsUsed,i)) {
3637               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3638               _G.nRegsSaved++;
3639
3640               if(!pic16_regWithIdx(i)->wasUsed) {
3641                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3642                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3643                 pic16_regWithIdx(i)->wasUsed = 1;
3644               }
3645             }
3646           }
3647           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3648         }
3649     }
3650         
3651     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3652 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3653 }
3654
3655 /*-----------------------------------------------------------------*/
3656 /* genEndFunction - generates epilogue for functions               */
3657 /*-----------------------------------------------------------------*/
3658 static void genEndFunction (iCode *ic)
3659 {
3660   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3661
3662     FENTRY;
3663
3664     if(IFFUNC_ISNAKED(sym->type)) {
3665       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3666       return;
3667     }
3668
3669     _G.stack_lat = 0;
3670
3671     /* add code for ISCRITICAL */
3672     if(IFFUNC_ISCRITICAL(sym->type)) {
3673       /* if critical function, turn on interrupts */
3674       
3675       /* TODO: add code here -- VR */
3676     }
3677     
3678     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3679           && sym->stack) {
3680       if (sym->stack == 1) {
3681         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg(&pic16_pc_fsr1l));
3682         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h));
3683       } else {
3684         // we have to add more than one...
3685         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc1)); // this holds a return value!
3686         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3687         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(&pic16_pc_fsr1l));
3688         emitSKPNC;
3689         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h));
3690         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3691         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_plusw1)); // this holds a retrun value!
3692       }
3693     }
3694
3695 //    sym->regsUsed = _G.fregsUsed;
3696     
3697     /* now we need to restore the registers */
3698     /* if any registers used */
3699     if (sym->regsUsed) {
3700       int i;
3701
3702         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3703         /* restore registers used */
3704         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3705         for ( i = sym->regsUsed->size; i >= 0; i--) {
3706           if (bitVectBitValue(sym->regsUsed,i)) {
3707             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3708             _G.nRegsSaved--;
3709           }
3710         }
3711         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3712
3713     }
3714
3715     if(strcmp(sym->name, "main")) {
3716       if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3717         /* restore stack frame */
3718         if(STACK_MODEL_LARGE)
3719           pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2h ));
3720 //          pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3721         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2l ));
3722 //        pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3723       }
3724     }
3725
3726     _G.useWreg = 0;
3727
3728     if (IFFUNC_ISISR(sym->type)) {
3729       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3730       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3731       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3732       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3733
3734       if(!(_G.interruptvector == 1)) {
3735         /* do not restore interrupt vector for WREG,STATUS,BSR
3736          * for high priority interrupt, see genFunction */
3737         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3738         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3739         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3740       }
3741       _G.interruptvector = 0;           /* sanity check */
3742
3743
3744       /* if debug then send end of function */
3745 /*      if (options.debug && currFunc)  */
3746       if (currFunc) {
3747         debugFile->writeEndFunction (currFunc, ic, 1);
3748       }
3749         
3750       if(_G.usefastretfie)
3751         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3752       else
3753         pic16_emitpcodeNULLop(POC_RETFIE);
3754
3755       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3756       
3757       _G.usefastretfie = 0;
3758       return;
3759     }
3760
3761     if (IFFUNC_ISCRITICAL(sym->type)) {
3762       pic16_emitcode("setb","ea");
3763     }
3764
3765     /* if debug then send end of function */
3766     if (currFunc) {
3767       debugFile->writeEndFunction (currFunc, ic, 1);
3768     }
3769
3770     /* insert code to restore stack frame, if user enabled it
3771      * and function is not main() */
3772          
3773
3774     pic16_emitpcodeNULLop(POC_RETURN);
3775
3776     /* Mark the end of a function */
3777     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3778 }
3779
3780
3781 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3782 {
3783   if(is_LitOp(op)) {
3784     unsigned long lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3785       if(lit == 0) {
3786         pic16_emitpcode(POC_CLRF, dest);
3787       } else {
3788         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3789         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3790       }
3791   } else {
3792     if(dest->type == PO_WREG && (offset == 0)) {
3793       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3794       return;
3795     }
3796     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3797   }
3798 }
3799
3800 /*-----------------------------------------------------------------*/
3801 /* genRet - generate code for return statement                     */
3802 /*-----------------------------------------------------------------*/
3803 static void genRet (iCode *ic)
3804 {
3805   int size;
3806   operand *left;
3807
3808     FENTRY;
3809         /* if we have no return value then
3810          * just generate the "ret" */
3811         
3812         if (!IC_LEFT(ic)) 
3813                 goto jumpret;       
3814     
3815         /* we have something to return then
3816          * move the return value into place */
3817         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3818         size = AOP_SIZE(IC_LEFT(ic));
3819
3820         if(size <= 4) {
3821                 if(size>3) {
3822                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3823 //                      pic16_emitpcode(POC_MOVFF,
3824 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3825                 }
3826                 if(size>2) {
3827                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3828 //                      pic16_emitpcode(POC_MOVFF,
3829 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3830                 }
3831                 if(size>1) {
3832                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3833 //                      pic16_emitpcode(POC_MOVFF,
3834 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3835                 }
3836
3837 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3838
3839                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3840 //              pic16_emitpcode(POC_MOVFF,
3841 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3842
3843         } else {
3844                 /* >32-bits, setup stack and FSR0 */
3845                 while (size--) {
3846 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3847 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3848
3849                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3850
3851 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3852                         GpsuedoStkPtr++;
3853                 }
3854                         
3855                 /* setup FSR0 */
3856                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3857                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3858
3859                 if(STACK_MODEL_LARGE) {
3860                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3861                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3862                 } else {
3863                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3864                 }
3865         }
3866                                 
3867 #if 0
3868         /* old code, left here for reference -- VR */    
3869         while (size--) {
3870           char *l ;
3871
3872                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3873                         /* #NOCHANGE */
3874                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3875                         pic16_emitpcomment("push %s",l);
3876                         pushed++;
3877                 } else {
3878                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3879                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3880                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3881                         
3882                         if (strcmp(fReturn[offset],l)) {
3883                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3884                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3885                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3886                                 } else {
3887                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3888                                 }
3889                                 
3890                                 if(size) {
3891                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3892                                 }
3893                                 offset++;
3894                         }
3895                 }
3896         }    
3897
3898         if (pushed) {
3899                 while(pushed) {
3900                         pushed--;
3901                         if (strcmp(fReturn[pushed],"a"))
3902                                 pic16_emitcode("pop",fReturn[pushed]);
3903                         else
3904                                 pic16_emitcode("pop","acc");
3905                 }
3906         }
3907 #endif
3908
3909
3910         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3911     
3912 jumpret:
3913         /* generate a jump to the return label
3914          * if the next is not the return statement */
3915         if (!(ic->next && ic->next->op == LABEL
3916                 && IC_LABEL(ic->next) == returnLabel)) {
3917         
3918                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3919                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3920         }
3921 }
3922
3923 /*-----------------------------------------------------------------*/
3924 /* genLabel - generates a label                                    */
3925 /*-----------------------------------------------------------------*/
3926 static void genLabel (iCode *ic)
3927 {
3928   FENTRY;
3929
3930   /* special case never generate */
3931   if (IC_LABEL(ic) == entryLabel)
3932     return ;
3933
3934   pic16_emitpLabel(IC_LABEL(ic)->key);
3935 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3936 }
3937
3938 /*-----------------------------------------------------------------*/
3939 /* genGoto - generates a goto                                      */
3940 /*-----------------------------------------------------------------*/
3941 //tsd
3942 static void genGoto (iCode *ic)
3943 {
3944   FENTRY;
3945   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3946 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3947 }
3948
3949
3950 /*-----------------------------------------------------------------*/
3951 /* genMultbits :- multiplication of bits                           */
3952 /*-----------------------------------------------------------------*/
3953 static void genMultbits (operand *left, 
3954                          operand *right, 
3955                          operand *result)
3956 {
3957   FENTRY;
3958
3959   if(!pic16_sameRegs(AOP(result),AOP(right)))
3960     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3961
3962   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3963   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3964   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3965
3966 }
3967
3968
3969 /*-----------------------------------------------------------------*/
3970 /* genMultOneByte : 8 bit multiplication & division                */
3971 /*-----------------------------------------------------------------*/
3972 static void genMultOneByte (operand *left,
3973                             operand *right,
3974                             operand *result)
3975 {
3976
3977   FENTRY;
3978   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3979   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3980
3981   /* (if two literals, the value is computed before) */
3982   /* if one literal, literal on the right */
3983   if (AOP_TYPE(left) == AOP_LIT){
3984     operand *t = right;
3985     right = left;
3986     left = t;
3987   }
3988
3989         /* size is already checked in genMult == 1 */
3990 //      size = AOP_SIZE(result);
3991
3992         if (AOP_TYPE(right) == AOP_LIT){
3993                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3994                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3995                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3996                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3997         } else {
3998                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3999                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4000                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4001                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4002         }
4003         
4004         pic16_genMult8X8_8 (left, right,result);
4005 }
4006
4007 /*-----------------------------------------------------------------*/
4008 /* genMultOneWord : 16 bit multiplication                          */
4009 /*-----------------------------------------------------------------*/
4010 static void genMultOneWord (operand *left,
4011                             operand *right,
4012                             operand *result)
4013 {
4014   FENTRY;
4015   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4016   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4017
4018   /* (if two literals, the value is computed before)
4019    * if one literal, literal on the right */
4020   if (AOP_TYPE(left) == AOP_LIT){
4021     operand *t = right;
4022     right = left;
4023     left = t;
4024   }
4025
4026   /* size is checked already == 2 */
4027 //  size = AOP_SIZE(result);
4028
4029   if (AOP_TYPE(right) == AOP_LIT) {
4030     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4031       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4032       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4033       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4034   } else {
4035     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4036       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4037       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4038       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4039   }
4040         
4041   pic16_genMult16X16_16(left, right,result);
4042 }
4043
4044 /*-----------------------------------------------------------------*/
4045 /* genMultOneLong : 32 bit multiplication                          */
4046 /*-----------------------------------------------------------------*/
4047 static void genMultOneLong (operand *left,
4048                             operand *right,
4049                             operand *result)
4050 {
4051   FENTRY;
4052   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4053   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4054
4055   /* (if two literals, the value is computed before)
4056    * if one literal, literal on the right */
4057   if (AOP_TYPE(left) == AOP_LIT){
4058     operand *t = right;
4059     right = left;
4060     left = t;
4061   }
4062
4063   /* size is checked already == 4 */
4064 //  size = AOP_SIZE(result);
4065
4066   if (AOP_TYPE(right) == AOP_LIT) {
4067     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4068         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4069         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4070         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4071   } else {
4072     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4073         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4074         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4075         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4076   }
4077         
4078   pic16_genMult32X32_32(left, right,result);
4079 }
4080
4081
4082
4083 /*-----------------------------------------------------------------*/
4084 /* genMult - generates code for multiplication                     */
4085 /*-----------------------------------------------------------------*/
4086 static void genMult (iCode *ic)
4087 {
4088   operand *left = IC_LEFT(ic);
4089   operand *right = IC_RIGHT(ic);
4090   operand *result= IC_RESULT(ic);   
4091
4092     FENTRY;
4093         /* assign the amsops */
4094         pic16_aopOp (left,ic,FALSE);
4095         pic16_aopOp (right,ic,FALSE);
4096         pic16_aopOp (result,ic,TRUE);
4097
4098         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4099
4100         /* special cases first *
4101         * both are bits */
4102         if (AOP_TYPE(left) == AOP_CRY
4103                 && AOP_TYPE(right)== AOP_CRY) {
4104                 genMultbits(left,right,result);
4105           goto release ;
4106         }
4107
4108         /* if both are of size == 1 */
4109         if(AOP_SIZE(left) == 1
4110                 && AOP_SIZE(right) == 1) {
4111                 genMultOneByte(left,right,result);
4112           goto release ;
4113         }
4114
4115         /* if both are of size == 2 */
4116         if(AOP_SIZE(left) == 2
4117                 && AOP_SIZE(right) == 2) {
4118                 genMultOneWord(left, right, result);
4119           goto release;
4120         }
4121         
4122         /* if both are of size == 4 */
4123         if(AOP_SIZE(left) == 4
4124                 && AOP_SIZE(right) == 4) {
4125                 genMultOneLong(left, right, result);
4126           goto release;
4127         }
4128         
4129         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4130
4131
4132         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4133         /* should have been converted to function call */
4134         assert(0) ;
4135
4136 release :
4137         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4138         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4139         pic16_freeAsmop(result,NULL,ic,TRUE); 
4140 }
4141
4142 /*-----------------------------------------------------------------*/
4143 /* genDivbits :- division of bits                                  */
4144 /*-----------------------------------------------------------------*/
4145 static void genDivbits (operand *left, 
4146                         operand *right, 
4147                         operand *result)
4148 {
4149   char *l;
4150
4151     FENTRY;
4152     /* the result must be bit */    
4153     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4154     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4155
4156     MOVA(l);    
4157
4158     pic16_emitcode("div","ab");
4159     pic16_emitcode("rrc","a");
4160     pic16_aopPut(AOP(result),"c",0);
4161 }
4162
4163 /*-----------------------------------------------------------------*/
4164 /* genDivOneByte : 8 bit division                                  */
4165 /*-----------------------------------------------------------------*/
4166 static void genDivOneByte (operand *left,
4167                            operand *right,
4168                            operand *result)
4169 {
4170   sym_link *opetype = operandType(result);
4171   char *l ;
4172   symbol *lbl ;
4173   int size,offset;
4174
4175         /* result = divident / divisor
4176          * - divident may be a register or a literal,
4177          * - divisor may be a register or a literal,
4178          * so there are 3 cases (literal / literal is optimized
4179          * by the front-end) to handle.
4180          * In addition we must handle signed and unsigned, which
4181          * result in 6 final different cases -- VR */
4182
4183     FENTRY;
4184     
4185     size = AOP_SIZE(result) - 1;
4186     offset = 1;
4187     /* signed or unsigned */
4188     if (SPEC_USIGN(opetype)) {
4189       pCodeOp *pct1,    /* count */
4190                 *pct2,  /* reste */
4191                 *pct3;  /* temp */
4192       symbol *label1, *label2, *label3;;
4193
4194
4195         /* unsigned is easy */
4196
4197         pct1 = pic16_popGetTempReg(1);
4198         pct2 = pic16_popGetTempReg(1);
4199         pct3 = pic16_popGetTempReg(1);
4200         
4201         label1 = newiTempLabel(NULL);
4202         label2 = newiTempLabel(NULL);
4203         label3 = newiTempLabel(NULL);
4204
4205         /* the following algorithm is extracted from divuint.c */
4206
4207         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4208         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4209         
4210         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4211
4212         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4213         
4214         pic16_emitpLabel(label1->key);
4215         
4216         emitCLRC;
4217         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4218
4219
4220         emitCLRC;
4221         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4222         
4223
4224         emitSKPNC;
4225         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4226         
4227         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4228         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4229         
4230         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4231         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4232         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4233         
4234         pic16_emitpLabel( label3->key );
4235         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4236         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4237         
4238         
4239
4240         pic16_emitpLabel(label2->key);
4241         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4242         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4243         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4244         
4245         /* result is in wreg */
4246         if(AOP_TYPE(result) != AOP_ACC)
4247                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4248
4249         pic16_popReleaseTempReg( pct3, 1);
4250         pic16_popReleaseTempReg( pct2, 1);
4251         pic16_popReleaseTempReg( pct1, 1);
4252
4253         return ;
4254     }
4255
4256     /* signed is a little bit more difficult */
4257
4258     /* save the signs of the operands */
4259     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4260     MOVA(l);    
4261     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4262     pic16_emitcode("push","acc"); /* save it on the stack */
4263
4264     /* now sign adjust for both left & right */
4265     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4266     MOVA(l);       
4267     lbl = newiTempLabel(NULL);
4268     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4269     pic16_emitcode("cpl","a");   
4270     pic16_emitcode("inc","a");
4271     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4272     pic16_emitcode("mov","b,a");
4273
4274     /* sign adjust left side */
4275     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4276     MOVA(l);
4277
4278     lbl = newiTempLabel(NULL);
4279     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4280     pic16_emitcode("cpl","a");
4281     pic16_emitcode("inc","a");
4282     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4283
4284     /* now the division */
4285     pic16_emitcode("div","ab");
4286     /* we are interested in the lower order
4287     only */
4288     pic16_emitcode("mov","b,a");
4289     lbl = newiTempLabel(NULL);
4290     pic16_emitcode("pop","acc");   
4291     /* if there was an over flow we don't 
4292     adjust the sign of the result */
4293     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4294     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4295     CLRC;
4296     pic16_emitcode("clr","a");
4297     pic16_emitcode("subb","a,b");
4298     pic16_emitcode("mov","b,a");
4299     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4300
4301     /* now we are done */
4302     pic16_aopPut(AOP(result),"b",0);
4303     if(size > 0){
4304         pic16_emitcode("mov","c,b.7");
4305         pic16_emitcode("subb","a,acc");   
4306     }
4307     while (size--)
4308         pic16_aopPut(AOP(result),"a",offset++);
4309
4310 }
4311
4312 /*-----------------------------------------------------------------*/
4313 /* genDiv - generates code for division                            */
4314 /*-----------------------------------------------------------------*/
4315 static void genDiv (iCode *ic)
4316 {
4317     operand *left = IC_LEFT(ic);
4318     operand *right = IC_RIGHT(ic);
4319     operand *result= IC_RESULT(ic);   
4320
4321
4322         /* Division is a very lengthy algorithm, so it is better
4323          * to call support routines than inlining algorithm.
4324          * Division functions written here just in case someone
4325          * wants to inline and not use the support libraries -- VR */
4326
4327     FENTRY;
4328     
4329     /* assign the amsops */
4330     pic16_aopOp (left,ic,FALSE);
4331     pic16_aopOp (right,ic,FALSE);
4332     pic16_aopOp (result,ic,TRUE);
4333
4334     /* special cases first */
4335     /* both are bits */
4336     if (AOP_TYPE(left) == AOP_CRY &&
4337         AOP_TYPE(right)== AOP_CRY) {
4338         genDivbits(left,right,result);
4339         goto release ;
4340     }
4341
4342     /* if both are of size == 1 */
4343     if (AOP_SIZE(left) == 1 &&
4344         AOP_SIZE(right) == 1 ) {
4345         genDivOneByte(left,right,result);
4346         goto release ;
4347     }
4348
4349     /* should have been converted to function call */
4350     assert(0);
4351 release :
4352     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4353     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4354     pic16_freeAsmop(result,NULL,ic,TRUE); 
4355 }
4356
4357 /*-----------------------------------------------------------------*/
4358 /* genModbits :- modulus of bits                                   */
4359 /*-----------------------------------------------------------------*/
4360 static void genModbits (operand *left, 
4361                         operand *right, 
4362                         operand *result)
4363 {
4364   char *l;
4365
4366     FENTRY;  
4367     
4368     werror(W_POSSBUG2, __FILE__, __LINE__);
4369     /* the result must be bit */    
4370     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4371     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4372
4373     MOVA(l);       
4374
4375     pic16_emitcode("div","ab");
4376     pic16_emitcode("mov","a,b");
4377     pic16_emitcode("rrc","a");
4378     pic16_aopPut(AOP(result),"c",0);
4379 }
4380
4381 /*-----------------------------------------------------------------*/
4382 /* genModOneByte : 8 bit modulus                                   */
4383 /*-----------------------------------------------------------------*/
4384 static void genModOneByte (operand *left,
4385                            operand *right,
4386                            operand *result)
4387 {
4388   sym_link *opetype = operandType(result);
4389   char *l ;
4390   symbol *lbl ;
4391
4392     FENTRY;
4393     werror(W_POSSBUG2, __FILE__, __LINE__);
4394
4395     /* signed or unsigned */
4396     if (SPEC_USIGN(opetype)) {
4397         /* unsigned is easy */
4398         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4399         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4400         MOVA(l);    
4401         pic16_emitcode("div","ab");
4402         pic16_aopPut(AOP(result),"b",0);
4403         return ;
4404     }
4405
4406     /* signed is a little bit more difficult */
4407
4408     /* save the signs of the operands */
4409     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4410     MOVA(l);
4411
4412     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4413     pic16_emitcode("push","acc"); /* save it on the stack */
4414
4415     /* now sign adjust for both left & right */
4416     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4417     MOVA(l);
4418
4419     lbl = newiTempLabel(NULL);
4420     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4421     pic16_emitcode("cpl","a");   
4422     pic16_emitcode("inc","a");
4423     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4424     pic16_emitcode("mov","b,a"); 
4425
4426     /* sign adjust left side */
4427     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4428     MOVA(l);
4429
4430     lbl = newiTempLabel(NULL);
4431     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4432     pic16_emitcode("cpl","a");   
4433     pic16_emitcode("inc","a");
4434     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4435
4436     /* now the multiplication */
4437     pic16_emitcode("div","ab");
4438     /* we are interested in the lower order
4439     only */
4440     lbl = newiTempLabel(NULL);
4441     pic16_emitcode("pop","acc");   
4442     /* if there was an over flow we don't 
4443     adjust the sign of the result */
4444     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4445     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4446     CLRC ;
4447     pic16_emitcode("clr","a");
4448     pic16_emitcode("subb","a,b");
4449     pic16_emitcode("mov","b,a");
4450     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4451
4452     /* now we are done */
4453     pic16_aopPut(AOP(result),"b",0);
4454
4455 }
4456
4457 /*-----------------------------------------------------------------*/
4458 /* genMod - generates code for division                            */
4459 /*-----------------------------------------------------------------*/
4460 static void genMod (iCode *ic)
4461 {
4462   operand *left = IC_LEFT(ic);
4463   operand *right = IC_RIGHT(ic);
4464   operand *result= IC_RESULT(ic);  
4465
4466     FENTRY;
4467     
4468     /* assign the amsops */
4469     pic16_aopOp (left,ic,FALSE);
4470     pic16_aopOp (right,ic,FALSE);
4471     pic16_aopOp (result,ic,TRUE);
4472
4473     /* special cases first */
4474     /* both are bits */
4475     if (AOP_TYPE(left) == AOP_CRY &&
4476         AOP_TYPE(right)== AOP_CRY) {
4477         genModbits(left,right,result);
4478         goto release ;
4479     }
4480
4481     /* if both are of size == 1 */
4482     if (AOP_SIZE(left) == 1 &&
4483         AOP_SIZE(right) == 1 ) {
4484         genModOneByte(left,right,result);
4485         goto release ;
4486     }
4487
4488     /* should have been converted to function call */
4489     assert(0);
4490
4491 release :
4492     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4493     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4494     pic16_freeAsmop(result,NULL,ic,TRUE); 
4495 }
4496
4497 /*-----------------------------------------------------------------*/
4498 /* genIfxJump :- will create a jump depending on the ifx           */
4499 /*-----------------------------------------------------------------*/
4500 /*
4501   note: May need to add parameter to indicate when a variable is in bit space.
4502 */
4503 static void genIfxJump (iCode *ic, char *jval)
4504 {
4505   FENTRY;
4506   
4507     /* if true label then we jump if condition
4508     supplied is true */
4509     if ( IC_TRUE(ic) ) {
4510
4511         if(strcmp(jval,"a") == 0)
4512           emitSKPZ;
4513         else if (strcmp(jval,"c") == 0)
4514           emitSKPC;
4515         else {
4516           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4517           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4518         }
4519
4520         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4521         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4522
4523     }
4524     else {
4525         /* false label is present */
4526         if(strcmp(jval,"a") == 0)
4527           emitSKPNZ;
4528         else if (strcmp(jval,"c") == 0)
4529           emitSKPNC;
4530         else {
4531           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4532           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4533         }
4534
4535         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4536         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4537
4538     }
4539
4540
4541     /* mark the icode as generated */
4542     ic->generated = 1;
4543 }
4544
4545 #if 0
4546 // not needed ATM
4547
4548 /*-----------------------------------------------------------------*/
4549 /* genSkip                                                         */
4550 /*-----------------------------------------------------------------*/
4551 static void genSkip(iCode *ifx,int status_bit)
4552 {
4553   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4554   if(!ifx)
4555     return;
4556
4557   if ( IC_TRUE(ifx) ) {
4558     switch(status_bit) {
4559     case 'z':
4560       emitSKPNZ;
4561       break;
4562
4563     case 'c':
4564       emitSKPNC;
4565       break;
4566
4567     case 'd':
4568       emitSKPDC;
4569       break;
4570
4571     }
4572
4573     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4574     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4575
4576   } else {
4577
4578     switch(status_bit) {
4579
4580     case 'z':
4581       emitSKPZ;
4582       break;
4583
4584     case 'c':
4585       emitSKPC;
4586       break;
4587
4588     case 'd':
4589       emitSKPDC;
4590       break;
4591     }
4592     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4593     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4594
4595   }
4596
4597 }
4598 #endif
4599
4600 /*-----------------------------------------------------------------*/
4601 /* genSkipc                                                        */
4602 /*-----------------------------------------------------------------*/
4603 static void genSkipc(resolvedIfx *rifx)
4604 {
4605   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4606   
4607   if(!rifx)
4608     return;
4609
4610   if(rifx->condition)
4611     emitSKPC;
4612   else
4613     emitSKPNC;
4614
4615   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4616   rifx->generated = 1;
4617 }
4618
4619 /*-----------------------------------------------------------------*/
4620 /* genSkipz2                                                       */
4621 /*-----------------------------------------------------------------*/
4622 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4623 {
4624   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4625   
4626   if(!rifx)
4627     return;
4628
4629   if( (rifx->condition ^ invert_condition) & 1)
4630     emitSKPZ;
4631   else
4632     emitSKPNZ;
4633
4634   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4635   rifx->generated = 1;
4636 }
4637
4638 #if 0
4639 /*-----------------------------------------------------------------*/
4640 /* genSkipz                                                        */
4641 /*-----------------------------------------------------------------*/
4642 static void genSkipz(iCode *ifx, int condition)
4643 {
4644   if(!ifx)
4645     return;
4646
4647   if(condition)
4648     emitSKPNZ;
4649   else
4650     emitSKPZ;
4651
4652   if ( IC_TRUE(ifx) )
4653     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4654   else
4655     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4656
4657   if ( IC_TRUE(ifx) )
4658     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4659   else
4660     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4661
4662 }
4663 #endif
4664
4665 /*-----------------------------------------------------------------*/
4666 /* genSkipCond                                                     */
4667 /*-----------------------------------------------------------------*/
4668 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4669 {
4670   if(!rifx)
4671     return;
4672
4673   if(rifx->condition)
4674     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4675   else
4676     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4677
4678
4679   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4680   rifx->generated = 1;
4681 }
4682
4683 #if 0
4684 /*-----------------------------------------------------------------*/
4685 /* genChkZeroes :- greater or less than comparison                 */
4686 /*     For each byte in a literal that is zero, inclusive or the   */
4687 /*     the corresponding byte in the operand with W                */
4688 /*     returns true if any of the bytes are zero                   */
4689 /*-----------------------------------------------------------------*/
4690 static int genChkZeroes(operand *op, int lit,  int size)
4691 {
4692
4693   int i;
4694   int flag =1;
4695
4696   while(size--) {
4697     i = (lit >> (size*8)) & 0xff;
4698
4699     if(i==0) {
4700       if(flag) 
4701         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4702       else
4703         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4704       flag = 0;
4705     }
4706   }
4707
4708   return (flag==0);
4709 }
4710 #endif
4711
4712 /*-----------------------------------------------------------------*/
4713 /* genCmp :- greater or less than comparison                       */
4714 /*-----------------------------------------------------------------*/
4715 #if 1
4716                 /* { */
4717       /* original code */
4718 static void genCmp (operand *left,operand *right,
4719                     operand *result, iCode *ifx, int sign)
4720 {
4721   int size; //, offset = 0 ;
4722   unsigned long lit = 0L,i = 0;
4723   resolvedIfx rFalseIfx;
4724   //  resolvedIfx rTrueIfx;
4725   symbol *truelbl;
4726   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4727 /*
4728   if(ifx) {
4729     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4730     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4731   }
4732 */
4733
4734   FENTRY;
4735   
4736   resolveIfx(&rFalseIfx,ifx);
4737   truelbl  = newiTempLabel(NULL);
4738   size = max(AOP_SIZE(left),AOP_SIZE(right));
4739
4740   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4741
4742 #define _swapp
4743
4744   /* if literal is on the right then swap with left */
4745   if ((AOP_TYPE(right) == AOP_LIT)) {
4746     operand *tmp = right ;
4747     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4748     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4749 #ifdef _swapp
4750
4751     lit = (lit - 1) & mask;
4752     right = left;
4753     left = tmp;
4754     rFalseIfx.condition ^= 1;
4755 #endif
4756
4757   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4758     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4759   }
4760
4761
4762   //if(IC_TRUE(ifx) == NULL)
4763   /* if left & right are bit variables */
4764   if (AOP_TYPE(left) == AOP_CRY &&
4765       AOP_TYPE(right) == AOP_CRY ) {
4766     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4767     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4768   } else {
4769     /* subtract right from left if at the
4770        end the carry flag is set then we know that
4771        left is greater than right */
4772
4773     symbol *lbl  = newiTempLabel(NULL);
4774
4775 #if 0
4776         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4777                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
4778 #endif
4779
4780 #ifndef _swapp
4781     if(AOP_TYPE(right) == AOP_LIT) {
4782
4783       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4784
4785       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4786
4787       /* special cases */
4788
4789       if(lit == 0) {
4790
4791         if(sign != 0) 
4792           genSkipCond(&rFalseIfx,left,size-1,7);
4793         else 
4794           /* no need to compare to 0...*/
4795           /* NOTE: this is a de-generate compare that most certainly 
4796            *       creates some dead code. */
4797           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4798
4799         if(ifx) ifx->generated = 1;
4800         return;
4801
4802       }
4803       size--;
4804
4805       if(size == 0) {
4806         //i = (lit >> (size*8)) & 0xff;
4807         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4808         
4809         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4810
4811         i = ((0-lit) & 0xff);
4812         if(sign) {
4813           if( i == 0x81) { 
4814             /* lit is 0x7f, all signed chars are less than
4815              * this except for 0x7f itself */
4816             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4817             genSkipz2(&rFalseIfx,0);
4818           } else {
4819             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4820             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4821             genSkipc(&rFalseIfx);
4822           }
4823
4824         } else {
4825           if(lit == 1) {
4826             genSkipz2(&rFalseIfx,1);
4827           } else {
4828             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4829             genSkipc(&rFalseIfx);
4830           }
4831         }
4832
4833         if(ifx) ifx->generated = 1;
4834         return;
4835       }
4836
4837       /* chars are out of the way. now do ints and longs */
4838
4839
4840       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4841         
4842       /* special cases */
4843
4844       if(sign) {
4845
4846         if(lit == 0) {
4847           genSkipCond(&rFalseIfx,left,size,7);
4848           if(ifx) ifx->generated = 1;
4849           return;
4850         }
4851
4852         if(lit <0x100) {
4853           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4854
4855           //rFalseIfx.condition ^= 1;
4856           //genSkipCond(&rFalseIfx,left,size,7);
4857           //rFalseIfx.condition ^= 1;
4858
4859           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4860           if(rFalseIfx.condition)
4861             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4862           else
4863             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4864
4865           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4866           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4867           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4868
4869           while(size > 1)
4870             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4871
4872           if(rFalseIfx.condition) {
4873             emitSKPZ;
4874             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4875
4876           } else {
4877             emitSKPNZ;
4878           }
4879
4880           genSkipc(&rFalseIfx);
4881           pic16_emitpLabel(truelbl->key);
4882           if(ifx) ifx->generated = 1;
4883           return;
4884
4885         }
4886
4887         if(size == 1) {
4888
4889           if( (lit & 0xff) == 0) {
4890             /* lower byte is zero */
4891             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4892             i = ((lit >> 8) & 0xff) ^0x80;
4893             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4894             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4895             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4896             genSkipc(&rFalseIfx);
4897
4898
4899             if(ifx) ifx->generated = 1;
4900             return;
4901
4902           }
4903         } else {
4904           /* Special cases for signed longs */
4905           if( (lit & 0xffffff) == 0) {
4906             /* lower byte is zero */
4907             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4908             i = ((lit >> 8*3) & 0xff) ^0x80;
4909             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4910             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4911             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4912             genSkipc(&rFalseIfx);
4913
4914
4915             if(ifx) ifx->generated = 1;
4916             return;
4917
4918           }
4919
4920         }
4921
4922
4923         if(lit & (0x80 << (size*8))) {
4924           /* lit is negative */
4925           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4926
4927           //genSkipCond(&rFalseIfx,left,size,7);
4928
4929           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4930
4931           if(rFalseIfx.condition)
4932             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4933           else
4934             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4935
4936
4937         } else {
4938           /* lit is positive */
4939           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4940           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4941           if(rFalseIfx.condition)
4942             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4943           else
4944             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4945
4946         }
4947
4948         /*
4949           This works, but is only good for ints.
4950           It also requires a "known zero" register.
4951           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4952           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4953           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4954           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4955           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4956           genSkipc(&rFalseIfx);
4957
4958           pic16_emitpLabel(truelbl->key);
4959           if(ifx) ifx->generated = 1;
4960           return;
4961         **/
4962           
4963         /* There are no more special cases, so perform a general compare */
4964   
4965         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4966         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4967
4968         while(size--) {
4969
4970           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4971           emitSKPNZ;
4972           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4973         }
4974         //rFalseIfx.condition ^= 1;
4975         genSkipc(&rFalseIfx);
4976
4977         pic16_emitpLabel(truelbl->key);
4978
4979         if(ifx) ifx->generated = 1;
4980         return;
4981
4982
4983       }
4984
4985
4986       /* sign is out of the way. So now do an unsigned compare */
4987       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4988
4989
4990       /* General case - compare to an unsigned literal on the right.*/
4991
4992       i = (lit >> (size*8)) & 0xff;
4993       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4994       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4995       while(size--) {
4996         i = (lit >> (size*8)) & 0xff;
4997
4998         if(i) {
4999           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5000           emitSKPNZ;
5001           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5002         } else {
5003           /* this byte of the lit is zero, 
5004            *if it's not the last then OR in the variable */
5005           if(size)
5006             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5007         }
5008       }
5009
5010
5011       pic16_emitpLabel(lbl->key);
5012 //      pic16_emitpLabel(truelbl->key);
5013       //if(emitFinalCheck)
5014       genSkipc(&rFalseIfx);
5015       if(sign)
5016         pic16_emitpLabel(truelbl->key);
5017
5018       if(ifx) ifx->generated = 1;
5019       return;
5020
5021
5022     }
5023 #endif  // _swapp
5024
5025     if(AOP_TYPE(left) == AOP_LIT) {
5026       //symbol *lbl = newiTempLabel(NULL);
5027
5028       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5029
5030
5031       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5032
5033       /* Special cases */
5034       if((lit == 0) && (sign == 0)){
5035
5036         size--;
5037         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5038         while(size) 
5039           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5040
5041         genSkipz2(&rFalseIfx,0);
5042         if(ifx) ifx->generated = 1;
5043         return;
5044       }
5045
5046       if(size==1) {
5047         /* Special cases */
5048         lit &= 0xff;
5049         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5050           /* degenerate compare can never be true */
5051           if(rFalseIfx.condition == 0)
5052             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5053
5054           if(ifx) ifx->generated = 1;
5055           return;
5056         }
5057
5058         if(sign) {
5059           /* signed comparisons to a literal byte */
5060
5061           int lp1 = (lit+1) & 0xff;
5062
5063           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5064           switch (lp1) {
5065           case 0:
5066             rFalseIfx.condition ^= 1;
5067             genSkipCond(&rFalseIfx,right,0,7);
5068             break;
5069           case 0x7f:
5070             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5071             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5072             genSkipz2(&rFalseIfx,1);
5073             break;
5074           default:
5075             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5076             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5077             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5078             rFalseIfx.condition ^= 1;
5079             genSkipc(&rFalseIfx);
5080             break;
5081           }
5082         } else {
5083           /* unsigned comparisons to a literal byte */
5084
5085           switch(lit & 0xff ) {
5086           case 0:
5087             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5088             genSkipz2(&rFalseIfx,0);
5089             break;
5090           case 0x7f:
5091             rFalseIfx.condition ^= 1;
5092             genSkipCond(&rFalseIfx,right,0,7);
5093             break;
5094
5095           default:
5096             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5097             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5098             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5099             rFalseIfx.condition ^= 1;
5100             if (AOP_TYPE(result) == AOP_CRY)
5101               genSkipc(&rFalseIfx);
5102             else {
5103               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5104               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5105             }         
5106             break;
5107           }
5108         }
5109
5110         if(ifx) ifx->generated = 1;
5111         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5112                 goto check_carry;
5113         return;
5114
5115       } else {
5116
5117         /* Size is greater than 1 */
5118
5119         if(sign) {
5120           int lp1 = lit+1;
5121
5122           size--;
5123
5124           if(lp1 == 0) {
5125             /* this means lit = 0xffffffff, or -1 */
5126
5127
5128             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5129             rFalseIfx.condition ^= 1;
5130             genSkipCond(&rFalseIfx,right,size,7);
5131             if(ifx) ifx->generated = 1;
5132
5133             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5134               goto check_carry;
5135
5136             return;
5137           }
5138
5139           if(lit == 0) {
5140             int s = size;
5141
5142             if(rFalseIfx.condition) {
5143               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5144               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5145             }
5146
5147             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5148             while(size--)
5149               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5150
5151
5152             emitSKPZ;
5153             if(rFalseIfx.condition) {
5154               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5155               pic16_emitpLabel(truelbl->key);
5156             }else {
5157               rFalseIfx.condition ^= 1;
5158               genSkipCond(&rFalseIfx,right,s,7);
5159             }
5160
5161             if(ifx) ifx->generated = 1;
5162
5163             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5164               goto check_carry;
5165
5166             return;
5167           }
5168
5169           if((size == 1) &&  (0 == (lp1&0xff))) {
5170             /* lower byte of signed word is zero */
5171             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5172             i = ((lp1 >> 8) & 0xff) ^0x80;
5173             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5174             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5175             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5176             rFalseIfx.condition ^= 1;
5177             genSkipc(&rFalseIfx);
5178
5179
5180             if(ifx) ifx->generated = 1;
5181
5182             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5183               goto check_carry;
5184
5185             return;
5186           }
5187
5188           if(lit & (0x80 << (size*8))) {
5189             /* Lit is less than zero */
5190             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5191             //rFalseIfx.condition ^= 1;
5192             //genSkipCond(&rFalseIfx,left,size,7);
5193             //rFalseIfx.condition ^= 1;
5194             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5195             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5196
5197             if(rFalseIfx.condition)
5198               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5199             else
5200               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5201
5202
5203           } else {
5204             /* Lit is greater than or equal to zero */
5205             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5206             //rFalseIfx.condition ^= 1;
5207             //genSkipCond(&rFalseIfx,right,size,7);
5208             //rFalseIfx.condition ^= 1;
5209
5210             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5211             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5212
5213             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5214             if(rFalseIfx.condition)
5215               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5216             else
5217               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5218
5219           }
5220
5221           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5222           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5223
5224           while(size--) {
5225
5226             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5227             emitSKPNZ;
5228             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5229           }
5230           rFalseIfx.condition ^= 1;
5231           //rFalseIfx.condition = 1;
5232           genSkipc(&rFalseIfx);
5233
5234           pic16_emitpLabel(truelbl->key);
5235
5236           if(ifx) ifx->generated = 1;
5237
5238
5239           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5240             goto check_carry;
5241
5242           return;
5243           // end of if (sign)
5244         } else {
5245
5246           /* compare word or long to an unsigned literal on the right.*/
5247
5248
5249           size--;
5250           if(lit < 0xff) {
5251             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5252             switch (lit) {
5253             case 0:
5254               break; /* handled above */
5255 /*
5256             case 0xff:
5257               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5258               while(size--)
5259                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5260               genSkipz2(&rFalseIfx,0);
5261               break;
5262 */
5263             default:
5264               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5265               while(--size)
5266                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5267
5268               emitSKPZ;
5269               if(rFalseIfx.condition)
5270                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5271               else
5272                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5273
5274
5275               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5276               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5277
5278               rFalseIfx.condition ^= 1;
5279               genSkipc(&rFalseIfx);
5280             }
5281
5282             pic16_emitpLabel(truelbl->key);
5283
5284             if(ifx) ifx->generated = 1;
5285
5286             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5287               goto check_carry;
5288
5289             return;
5290           }
5291
5292
5293           lit++;
5294           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5295           i = (lit >> (size*8)) & 0xff;
5296
5297           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5298           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5299
5300           while(size--) {
5301             i = (lit >> (size*8)) & 0xff;
5302
5303             if(i) {
5304               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5305               emitSKPNZ;
5306               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5307             } else {
5308               /* this byte of the lit is zero, 
5309                * if it's not the last then OR in the variable */
5310               if(size)
5311                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5312             }
5313           }
5314
5315
5316           pic16_emitpLabel(lbl->key);
5317
5318           rFalseIfx.condition ^= 1;
5319
5320           genSkipc(&rFalseIfx);
5321         }
5322
5323         if(sign)
5324           pic16_emitpLabel(truelbl->key);
5325         if(ifx) ifx->generated = 1;
5326
5327             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5328               goto check_carry;
5329
5330         return;
5331       }
5332     }
5333     /* Compare two variables */
5334
5335     DEBUGpic16_emitcode(";sign","%d",sign);
5336
5337     size--;
5338     if(sign) {
5339       /* Sigh. thus sucks... */
5340       if(size) {
5341         pCodeOp *pctemp;
5342         
5343         pctemp = pic16_popGetTempReg(1);
5344         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5345         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5346         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5347         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5348         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5349         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5350         pic16_popReleaseTempReg(pctemp, 1);
5351       } else {
5352         /* Signed char comparison */
5353         /* Special thanks to Nikolai Golovchenko for this snippet */
5354         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5355         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5356         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5357         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5358         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5359         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5360
5361         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5362         genSkipc(&rFalseIfx);
5363           
5364         if(ifx) ifx->generated = 1;
5365
5366             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5367               goto check_carry;
5368
5369         return;
5370       }
5371
5372     } else {
5373
5374       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5375       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5376     }
5377
5378
5379     /* The rest of the bytes of a multi-byte compare */
5380     while (size) {
5381
5382       emitSKPZ;
5383       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5384       size--;
5385
5386       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5387       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5388
5389
5390     }
5391
5392     pic16_emitpLabel(lbl->key);
5393
5394     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5395     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5396         (AOP_TYPE(result) == AOP_REG)) {
5397       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5398       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5399     } else {
5400       genSkipc(&rFalseIfx);
5401     }         
5402     //genSkipc(&rFalseIfx);
5403     if(ifx) ifx->generated = 1;
5404
5405
5406             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5407               goto check_carry;
5408
5409     return;
5410
5411   }
5412
5413 check_carry:
5414   if ((AOP_TYPE(result) != AOP_CRY) 
5415         && AOP_SIZE(result)) {
5416     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5417
5418     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5419
5420     pic16_outBitC(result);
5421   } else {
5422     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5423     /* if the result is used in the next
5424        ifx conditional branch then generate
5425        code a little differently */
5426     if (ifx )
5427       genIfxJump (ifx,"c");
5428     else
5429       pic16_outBitC(result);
5430     /* leave the result in acc */
5431   }
5432
5433 }
5434
5435 #else   /* old version of genCmp() */   /* } else { */
5436
5437 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5438 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5439         operand *result, int offset, int invert_op)
5440 {
5441   /* add code here */
5442   
5443   /* check condition, > or < ?? */
5444   if(rIfx->condition != 0)invert_op ^= 1;
5445   
5446   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5447
5448   if(!ifx)invert_op ^= 1;
5449
5450   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5451       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5452   
5453   /* do selection */
5454   if(!invert_op)return POC_CPFSGT;
5455   else return POC_CPFSLT;
5456 }
5457
5458 static int compareAopfirstpass=1;
5459
5460 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5461             operand *oper, int offset, operand *result,
5462             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5463             symbol *tlbl)
5464 {
5465   int op;
5466   symbol *truelbl;
5467
5468   /* invert if there is a result to be loaded, in order to fit,
5469    * SETC/CLRC sequence */
5470   if(AOP_SIZE(result))invert_op ^= 1;
5471
5472 //  if(sign && !offset)invert_op ^= 1;
5473   
5474 //  if(sign)invert_op ^= 1;
5475   
5476   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5477
5478   if(AOP_SIZE(result) && compareAopfirstpass) {
5479     if(!ifx) {
5480       if(pcop2)
5481         pic16_emitpcode(POC_SETF, pcop2);
5482       else
5483         emitSETC;
5484     } else {
5485       if(pcop2)
5486         pic16_emitpcode(POC_CLRF, pcop2);
5487       else
5488         emitCLRC;
5489     }
5490   }
5491
5492   compareAopfirstpass = 0;
5493
5494       /* there is a bug when comparing operands with size > 1,
5495        * because higher bytes can be equal and test should be performed
5496        * to the next lower byte, current algorithm, considers operands
5497        * inequal in these cases! -- VR 20041107 */
5498
5499     
5500   if(pcop)
5501     pic16_emitpcode(op, pcop);
5502   else
5503     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5504
5505
5506   if((!sign || !offset) && AOP_SIZE(result)) {
5507     if(!ifx) {
5508       if(pcop2)
5509         pic16_emitpcode(POC_CLRF, pcop2);
5510         else
5511         emitCLRC;
5512     } else {
5513       if(pcop2)
5514         pic16_emitpcode(POC_SETF, pcop2);
5515       else
5516         emitSETC;
5517     }
5518     
5519     /* don't emit final branch (offset == 0) */
5520     if(offset) {
5521
5522       if(pcop2)
5523         pic16_emitpcode(POC_RRCF, pcop2);
5524
5525       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5526     }
5527   } else {
5528     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5529       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5530             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5531
5532       truelbl = newiTempLabel( NULL );
5533       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5534       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5535         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5536       else
5537         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5538       pic16_emitpLabel(truelbl->key);
5539     } else {
5540       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5541     }
5542   }
5543 }
5544
5545
5546   
5547
5548 #if 1   /* { */
5549 static void genCmp (operand *left, operand *right,
5550                     operand *result, iCode *ifx, int sign)
5551 {
5552   int size, cmpop=1;
5553   long lit = 0L;
5554   resolvedIfx rFalseIfx;
5555   symbol *falselbl, *tlbl;
5556
5557     FENTRY;
5558     
5559     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5560
5561     resolveIfx(&rFalseIfx, ifx);
5562     size = max(AOP_SIZE(left), AOP_SIZE(right));
5563     
5564     /* if left & right are bit variables */
5565     if(AOP_TYPE(left) == AOP_CRY
5566       && AOP_TYPE(right) == AOP_CRY ) {
5567
5568         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5569         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5570         
5571         werror(W_POSSBUG2, __FILE__, __LINE__);
5572         exit(-1);
5573     }
5574     
5575     /* if literal is on the right then swap with left */
5576     if((AOP_TYPE(right) == AOP_LIT)) {
5577       operand *tmp = right ;
5578 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
5579
5580         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5581
5582 //      lit = (lit - 1) & mask;
5583         right = left;
5584         left = tmp;
5585         rFalseIfx.condition ^= 1;               /* reverse compare */
5586     } else
5587     if ((AOP_TYPE(left) == AOP_LIT)) {
5588       /* float compares are handled by support functions */
5589       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5590     }
5591
5592     /* actual comparing algorithm */
5593 //    size = AOP_SIZE( right );
5594
5595     falselbl = newiTempLabel( NULL );
5596     if(AOP_TYPE(left) == AOP_LIT) {
5597       /* compare to literal */
5598       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5599       
5600       if(sign) {
5601         pCodeOp *pct, *pct2;
5602         symbol *tlbl1;
5603
5604         /* signed compare */
5605         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5606
5607         pct = pic16_popCopyReg(&pic16_pc_prodl);
5608         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5609         tlbl = newiTempLabel( NULL );
5610         
5611         /* first compare signs:
5612          *  a. if both are positive, compare just like unsigned
5613          *  b. if both are negative, invert cmpop, compare just like unsigned
5614          *  c. if different signs, determine the result directly */
5615
5616         size--;
5617
5618 #if 1
5619         /* { */
5620         tlbl1 = newiTempLabel( NULL );
5621 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
5622
5623         if(lit > 0) {
5624
5625           /* literal is zero or positive:
5626            *  a. if carry is zero, too, continue compare,
5627            *  b. if carry is set, then continue depending on cmpop ^ condition:
5628            *    1. '<' return false (literal < variable),
5629            *    2. '>' return true (literal > variable) */
5630 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
5631           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5632           
5633           
5634           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5635           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
5636         } else 
5637         if(lit < 0) {
5638           
5639           /* literal is negative:
5640            *  a. if carry is set, too, continue compare,
5641            *  b. if carry is zero, then continue depending on cmpop ^ condition:
5642            *    1. '<' return true (literal < variable),
5643            *    2. '>' return false (literal > variable) */
5644 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
5645           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5646           
5647           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5648           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5649         }
5650 #if 1
5651         else {
5652           /* lit == 0 */
5653           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5654           
5655           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5656           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5657         }
5658 #endif
5659         
5660         
5661         pic16_emitpLabel( tlbl1->key );
5662 #endif  /* } */
5663
5664         compareAopfirstpass=1;
5665 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5666 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5667 //        pic16_emitpcode(POC_MOVWF, pct);
5668
5669 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5670         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5671 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5672         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5673
5674         /* generic case */        
5675           while( size-- ) {
5676 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5677 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
5678 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5679 //            pic16_emitpcode(POC_MOVWF, pct);
5680
5681 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5682             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
5683             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5684 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5685 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
5686           }
5687 //        }
5688         
5689         if(ifx)ifx->generated = 1;
5690
5691         if(AOP_SIZE(result)) {
5692           pic16_emitpLabel(tlbl->key);
5693           pic16_emitpLabel(falselbl->key);
5694           pic16_outBitOp( result, pct2 );
5695         } else {
5696           pic16_emitpLabel(tlbl->key);
5697         }
5698       } else {
5699
5700
5701         /* unsigned compare */      
5702         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
5703     
5704         compareAopfirstpass=1;
5705         while(size--) {
5706           
5707           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5708           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
5709
5710         }
5711
5712         if(ifx)ifx->generated = 1;
5713
5714
5715         if(AOP_SIZE(result)) {
5716           pic16_emitpLabel(falselbl->key);
5717           pic16_outBitC( result );
5718         }
5719
5720       }
5721     } else {
5722       /* compare registers */
5723       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
5724
5725
5726       if(sign) {
5727         pCodeOp *pct, *pct2;
5728         
5729         /* signed compare */
5730         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5731
5732         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
5733         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
5734         tlbl = newiTempLabel( NULL );
5735         
5736         compareAopfirstpass=1;
5737
5738         size--;
5739         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
5740 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5741         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5742         pic16_emitpcode(POC_MOVWF, pct);
5743
5744         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
5745 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5746         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5747
5748         /* WREG already holds left + 0x80 */
5749         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5750         
5751         while( size-- ) {
5752           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
5753 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5754           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5755           pic16_emitpcode(POC_MOVWF, pct);
5756                 
5757           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
5758 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5759           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5760
5761           /* WREG already holds left + 0x80 */
5762           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5763 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
5764         }
5765         
5766         if(ifx)ifx->generated = 1;
5767
5768         if(AOP_SIZE(result)) {
5769           pic16_emitpLabel(tlbl->key);
5770           pic16_emitpLabel(falselbl->key);
5771           pic16_outBitOp( result, pct2 );
5772         } else {
5773           pic16_emitpLabel(tlbl->key);
5774         }
5775
5776       } else {
5777         /* unsigned compare */      
5778         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
5779
5780         compareAopfirstpass=1;
5781         while(size--) {
5782           
5783           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
5784           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
5785
5786         }
5787
5788         if(ifx)ifx->generated = 1;
5789         if(AOP_SIZE(result)) {
5790
5791           pic16_emitpLabel(falselbl->key);
5792           pic16_outBitC( result );
5793         }
5794
5795       }
5796     }
5797 }
5798
5799 #else    /* } else { */
5800
5801 /* new version of genCmp -- VR 20041012 */
5802 static void genCmp (operand *left,operand *right,
5803                     operand *result, iCode *ifx, int sign)
5804 {
5805   int size; //, offset = 0 ;
5806   unsigned long lit = 0L,i = 0;
5807   resolvedIfx rFalseIfx;
5808   int willCheckCarry=0;
5809   //  resolvedIfx rTrueIfx;
5810   symbol *truelbl;
5811
5812     FENTRY;
5813   
5814   /* General concept:
5815    * subtract right from left if at the end the carry flag is set then we
5816    * know that left is greater than right */
5817             
5818   resolveIfx(&rFalseIfx,ifx);
5819   truelbl  = newiTempLabel(NULL);
5820   size = max(AOP_SIZE(left),AOP_SIZE(right));
5821
5822   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5823
5824   /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
5825    * POC_CPFSLT compare f, wreg, skip if f less then wreg */
5826   
5827
5828   /* if literal is on the right then swap with left */
5829   if ((AOP_TYPE(right) == AOP_LIT)) {
5830     operand *tmp = right ;
5831     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5832
5833       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5834
5835 //      lit = (lit - 1) & mask;
5836       right = left;
5837       left = tmp;
5838       rFalseIfx.condition ^= 1;         /* reverse compare */
5839   } else
5840   if ((AOP_TYPE(left) == AOP_LIT)) {
5841     /* float compares are handled by support functions */
5842     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5843   }
5844
5845
5846   //if(IC_TRUE(ifx) == NULL)
5847   /* if left & right are bit variables */
5848   if (AOP_TYPE(left) == AOP_CRY &&
5849       AOP_TYPE(right) == AOP_CRY ) {
5850
5851     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5852     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5853
5854   } else {
5855     symbol *lbl  = newiTempLabel(NULL);
5856
5857     if(AOP_TYPE(left) == AOP_LIT) {
5858       DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
5859
5860       if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5861         willCheckCarry = 1;
5862       else willCheckCarry = 0;
5863
5864       /* Special cases */
5865       if((lit == 0) && (sign == 0)) {
5866         /* unsigned compare to 0 */
5867         DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
5868         
5869         size--;
5870         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5871         while(size) 
5872           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5873
5874         genSkipz2(&rFalseIfx,0);
5875         if(ifx)ifx->generated = 1;
5876         return;
5877       }
5878
5879       if(size==1) {
5880         /* Special cases */
5881         lit &= 0xff;
5882         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5883           /* degenerate compare can never be true */
5884           if(rFalseIfx.condition == 0)
5885             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5886
5887           if(ifx) ifx->generated = 1;
5888           return;
5889         }
5890
5891         if(sign) {
5892           /* signed comparisons to a literal byte */
5893           DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
5894
5895           int lp1 = (lit+1) & 0xff;
5896
5897           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
5898           switch (lp1) {
5899           case 0:
5900             rFalseIfx.condition ^= 1;
5901             genSkipCond(&rFalseIfx,right,0,7);
5902             break;
5903           case 0x7f:
5904             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5905             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5906             genSkipz2(&rFalseIfx,1);
5907             break;
5908           default:
5909             pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
5910             
5911             if(rFalseIfx.condition)
5912               pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
5913             else
5914               pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
5915
5916             if(willCheckCarry) {
5917               if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
5918               else { emitSETC; emitCLRC; }
5919               
5920             } else {
5921               pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5922             }              
5923                       
5924 /*          pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5925             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5926             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5927             rFalseIfx.condition ^= 1;
5928             genSkipc(&rFalseIfx);
5929 */
5930             break;
5931           }
5932         } else {
5933           /* unsigned comparisons to a literal byte */
5934           DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
5935
5936           switch(lit & 0xff ) {
5937                           /* special cases */
5938           case 0:
5939             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5940             genSkipz2(&rFalseIfx,0);
5941             break;
5942           case 0x7f:
5943             rFalseIfx.condition ^= 1;
5944             genSkipCond(&rFalseIfx,right,0,7);
5945             break;
5946           default:
5947             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5948             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5949             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5950             rFalseIfx.condition ^= 1;
5951             if (AOP_TYPE(result) == AOP_CRY)
5952               genSkipc(&rFalseIfx);
5953             else {
5954               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5955               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5956             }         
5957             break;
5958           }
5959         }
5960
5961         if(ifx) ifx->generated = 1;
5962         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5963                 goto check_carry;
5964         return;
5965
5966       } else {
5967
5968         /* Size is greater than 1 */
5969
5970         if(sign) {
5971           int lp1 = lit+1;
5972
5973           size--;
5974
5975           if(lp1 == 0) {
5976             /* this means lit = 0xffffffff, or -1 */
5977
5978
5979             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5980             rFalseIfx.condition ^= 1;
5981             genSkipCond(&rFalseIfx,right,size,7);
5982             if(ifx) ifx->generated = 1;
5983             return;
5984           }
5985
5986           if(lit == 0) {
5987             int s = size;
5988
5989             if(rFalseIfx.condition) {
5990               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5991               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5992             }
5993
5994             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5995             while(size--)
5996               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5997
5998
5999             emitSKPZ;
6000             if(rFalseIfx.condition) {
6001               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6002               pic16_emitpLabel(truelbl->key);
6003             }else {
6004               rFalseIfx.condition ^= 1;
6005               genSkipCond(&rFalseIfx,right,s,7);
6006             }
6007
6008             if(ifx) ifx->generated = 1;
6009             return;
6010           }
6011
6012           if((size == 1) &&  (0 == (lp1&0xff))) {
6013             /* lower byte of signed word is zero */
6014             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
6015             i = ((lp1 >> 8) & 0xff) ^0x80;
6016             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6017             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6018             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6019             rFalseIfx.condition ^= 1;
6020             genSkipc(&rFalseIfx);
6021
6022
6023             if(ifx) ifx->generated = 1;
6024             return;
6025           }
6026
6027           if(lit & (0x80 << (size*8))) {
6028             /* Lit is less than zero */
6029             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
6030             //rFalseIfx.condition ^= 1;
6031             //genSkipCond(&rFalseIfx,left,size,7);
6032             //rFalseIfx.condition ^= 1;
6033             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6034             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6035
6036             if(rFalseIfx.condition)
6037               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6038             else
6039               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6040
6041
6042           } else {
6043             /* Lit is greater than or equal to zero */
6044             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
6045             //rFalseIfx.condition ^= 1;
6046             //genSkipCond(&rFalseIfx,right,size,7);
6047             //rFalseIfx.condition ^= 1;
6048
6049             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6050             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6051
6052             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6053             if(rFalseIfx.condition)
6054               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6055             else
6056               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6057
6058           }
6059
6060
6061           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6062           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6063
6064           while(size--) {
6065
6066             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6067             emitSKPNZ;
6068             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6069           }
6070           rFalseIfx.condition ^= 1;
6071           //rFalseIfx.condition = 1;
6072           genSkipc(&rFalseIfx);
6073
6074           pic16_emitpLabel(truelbl->key);
6075
6076           if(ifx) ifx->generated = 1;
6077           return;
6078           // end of if (sign)
6079         } else {
6080
6081           /* compare word or long to an unsigned literal on the right.*/
6082
6083
6084           size--;
6085           if(lit < 0xff) {
6086             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6087             switch (lit) {
6088             case 0:
6089               break; /* handled above */
6090 /*
6091             case 0xff:
6092               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6093               while(size--)
6094                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6095               genSkipz2(&rFalseIfx,0);
6096               break;
6097 */
6098             default:
6099               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6100               while(--size)
6101                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6102
6103               emitSKPZ;
6104               if(rFalseIfx.condition)
6105                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6106               else
6107                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6108
6109
6110               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6111               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6112
6113               rFalseIfx.condition ^= 1;
6114               genSkipc(&rFalseIfx);
6115             }
6116
6117             pic16_emitpLabel(truelbl->key);
6118
6119             if(ifx) ifx->generated = 1;
6120             return;
6121           }
6122
6123
6124           lit++;
6125           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6126           i = (lit >> (size*8)) & 0xff;
6127
6128           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6129           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6130
6131           while(size--) {
6132             i = (lit >> (size*8)) & 0xff;
6133
6134             if(i) {
6135               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6136               emitSKPNZ;
6137               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6138             } else {
6139               /* this byte of the lit is zero, 
6140                * if it's not the last then OR in the variable */
6141               if(size)
6142                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6143             }
6144           }
6145
6146
6147           pic16_emitpLabel(lbl->key);
6148
6149           rFalseIfx.condition ^= 1;
6150
6151           genSkipc(&rFalseIfx);
6152         }
6153
6154         if(sign)
6155           pic16_emitpLabel(truelbl->key);
6156         if(ifx) ifx->generated = 1;
6157         return;
6158       }
6159     }
6160     /* Compare two variables */
6161
6162     DEBUGpic16_emitcode(";sign","%d",sign);
6163
6164     size--;
6165     if(sign) {
6166       /* Sigh. thus sucks... */
6167       if(size) {
6168         pCodeOp *pctemp;
6169         
6170         pctemp = pic16_popGetTempReg(1);
6171         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6172         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6173         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6174         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6175         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6176         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6177         pic16_popReleaseTempReg(pctemp, 1);
6178       } else {
6179         /* Signed char comparison */
6180         /* Special thanks to Nikolai Golovchenko for this snippet */
6181         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6182         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6183         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
6184         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6185         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6186         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6187
6188         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6189         genSkipc(&rFalseIfx);
6190           
6191         if(ifx) ifx->generated = 1;
6192         return;
6193       }
6194
6195     } else {
6196
6197       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6198       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6199     }
6200
6201
6202     /* The rest of the bytes of a multi-byte compare */
6203     while (size) {
6204
6205       emitSKPZ;
6206       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
6207       size--;
6208
6209       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6210       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6211
6212
6213     }
6214
6215     pic16_emitpLabel(lbl->key);
6216
6217     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6218     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
6219         (AOP_TYPE(result) == AOP_REG)) {
6220       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6221       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6222     } else {
6223       genSkipc(&rFalseIfx);
6224     }         
6225     //genSkipc(&rFalseIfx);
6226     if(ifx) ifx->generated = 1;
6227
6228     return;
6229
6230   }
6231
6232 check_carry:
6233   if ((AOP_TYPE(result) != AOP_CRY) 
6234         && AOP_SIZE(result)) {
6235     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6236
6237     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6238
6239     pic16_outBitC(result);
6240   } else {
6241     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6242     /* if the result is used in the next
6243        ifx conditional branch then generate
6244        code a little differently */
6245     if (ifx )
6246       genIfxJump (ifx,"c");
6247     else
6248       pic16_outBitC(result);
6249     /* leave the result in acc */
6250   }
6251
6252 }
6253 #endif  /* } */
6254
6255
6256 #endif  /* } */
6257
6258
6259
6260 /*-----------------------------------------------------------------*/
6261 /* genCmpGt :- greater than comparison                             */
6262 /*-----------------------------------------------------------------*/
6263 static void genCmpGt (iCode *ic, iCode *ifx)
6264 {
6265   operand *left, *right, *result;
6266   sym_link *letype , *retype;
6267   int sign ;
6268
6269     FENTRY;
6270     
6271     left = IC_LEFT(ic);
6272     right= IC_RIGHT(ic);
6273     result = IC_RESULT(ic);
6274
6275     letype = getSpec(operandType(left));
6276     retype =getSpec(operandType(right));
6277     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6278     /* assign the amsops */
6279     pic16_aopOp (left,ic,FALSE);
6280     pic16_aopOp (right,ic,FALSE);
6281     pic16_aopOp (result,ic,TRUE);
6282
6283     genCmp(right, left, result, ifx, sign);
6284
6285     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6286     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6287     pic16_freeAsmop(result,NULL,ic,TRUE); 
6288 }
6289
6290 /*-----------------------------------------------------------------*/
6291 /* genCmpLt - less than comparisons                                */
6292 /*-----------------------------------------------------------------*/
6293 static void genCmpLt (iCode *ic, iCode *ifx)
6294 {
6295   operand *left, *right, *result;
6296   sym_link *letype , *retype;
6297   int sign ;
6298
6299     FENTRY;
6300
6301     left = IC_LEFT(ic);
6302     right= IC_RIGHT(ic);
6303     result = IC_RESULT(ic);
6304
6305     letype = getSpec(operandType(left));
6306     retype =getSpec(operandType(right));
6307     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6308
6309     /* assign the amsops */
6310     pic16_aopOp (left,ic,FALSE);
6311     pic16_aopOp (right,ic,FALSE);
6312     pic16_aopOp (result,ic,TRUE);
6313
6314     genCmp(left, right, result, ifx, sign);
6315
6316     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6317     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6318     pic16_freeAsmop(result,NULL,ic,TRUE); 
6319 }
6320
6321 #if 0
6322 // not needed ATM
6323 // FIXME reenable literal optimisation when the pic16 port is stable
6324
6325 /*-----------------------------------------------------------------*/
6326 /* genc16bit2lit - compare a 16 bit value to a literal             */
6327 /*-----------------------------------------------------------------*/
6328 static void genc16bit2lit(operand *op, int lit, int offset)
6329 {
6330   int i;
6331
6332   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6333   if( (lit&0xff) == 0) 
6334     i=1;
6335   else
6336     i=0;
6337
6338   switch( BYTEofLONG(lit,i)) { 
6339   case 0:
6340     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6341     break;
6342   case 1:
6343     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6344     break;
6345   case 0xff:
6346     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6347     break;
6348   default:
6349     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6350     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6351   }
6352
6353   i ^= 1;
6354
6355   switch( BYTEofLONG(lit,i)) { 
6356   case 0:
6357     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6358     break;
6359   case 1:
6360     emitSKPNZ;
6361     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6362     break;
6363   case 0xff:
6364     emitSKPNZ;
6365     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6366     break;
6367   default:
6368     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6369     emitSKPNZ;
6370     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6371
6372   }
6373
6374 }
6375 #endif
6376
6377 #if 0
6378 // not needed ATM
6379 /*-----------------------------------------------------------------*/
6380 /* gencjneshort - compare and jump if not equal                    */
6381 /*-----------------------------------------------------------------*/
6382 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6383 {
6384   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6385   int offset = 0;
6386   int res_offset = 0;  /* the result may be a different size then left or right */
6387   int res_size = AOP_SIZE(result);
6388   resolvedIfx rIfx;
6389   symbol *lbl, *lbl_done;
6390
6391   unsigned long lit = 0L;
6392   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6393
6394   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6395   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6396   if(result)
6397     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6398   resolveIfx(&rIfx,ifx);
6399   lbl =  newiTempLabel(NULL);
6400   lbl_done =  newiTempLabel(NULL);
6401
6402
6403   /* if the left side is a literal or 
6404      if the right is in a pointer register and left 
6405      is not */
6406   if ((AOP_TYPE(left) == AOP_LIT) || 
6407       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6408     operand *t = right;
6409     right = left;
6410     left = t;
6411   }
6412   if(AOP_TYPE(right) == AOP_LIT)
6413     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6414
6415   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6416     preserve_result = 1;
6417
6418   if(result && !preserve_result)
6419     {
6420       int i;
6421       for(i = 0; i < AOP_SIZE(result); i++)
6422         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6423     }
6424
6425
6426   /* if the right side is a literal then anything goes */
6427   if (AOP_TYPE(right) == AOP_LIT &&
6428       AOP_TYPE(left) != AOP_DIR ) {
6429     switch(size) {
6430     case 2:
6431       genc16bit2lit(left, lit, 0);
6432       emitSKPZ;
6433       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6434       break;
6435     default:
6436       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6437       while (size--) {
6438         if(lit & 0xff) {
6439           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6440           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6441         } else {
6442           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6443         }
6444
6445         emitSKPZ;
6446         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6447         offset++;
6448         if(res_offset < res_size-1)
6449           res_offset++;
6450         lit >>= 8;
6451       }
6452       break;
6453     }
6454   }
6455
6456   /* if the right side is in a register or in direct space or
6457      if the left is a pointer register & right is not */    
6458   else if (AOP_TYPE(right) == AOP_REG ||
6459            AOP_TYPE(right) == AOP_DIR || 
6460            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6461            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6462     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6463     int lbl_key = lbl->key;
6464
6465     if(result) {
6466       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6467       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6468     }else {
6469       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6470       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6471               __FUNCTION__,__LINE__);
6472       return;
6473     }
6474    
6475 /*     switch(size) { */
6476 /*     case 2: */
6477 /*       genc16bit2lit(left, lit, 0); */
6478 /*       emitSKPNZ; */
6479 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6480 /*       break; */
6481 /*     default: */
6482     while (size--) {
6483       int emit_skip=1;
6484       if((AOP_TYPE(left) == AOP_DIR) && 
6485          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6486
6487         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6488         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6489
6490       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6491             
6492         switch (lit & 0xff) {
6493         case 0:
6494           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6495           break;
6496         case 1:
6497           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6498           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6499           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6500           emit_skip=0;
6501           break;
6502         case 0xff:
6503           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6504           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6505           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6506           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6507           emit_skip=0;
6508           break;
6509         default:
6510           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6511           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6512         }
6513         lit >>= 8;
6514
6515       } else {
6516         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6517       }
6518       if(emit_skip) {
6519         if(AOP_TYPE(result) == AOP_CRY) {
6520           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6521           if(rIfx.condition)
6522             emitSKPNZ;
6523           else
6524             emitSKPZ;
6525           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6526         } else {
6527           /* fix me. probably need to check result size too */
6528           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6529           if(rIfx.condition)
6530             emitSKPZ;
6531           else
6532             emitSKPNZ;
6533           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6534           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6535         }
6536         if(ifx)
6537           ifx->generated=1;
6538       }
6539       emit_skip++;
6540       offset++;
6541       if(res_offset < res_size-1)
6542         res_offset++;
6543     }
6544 /*       break; */
6545 /*     } */
6546   } else if(AOP_TYPE(right) == AOP_REG &&
6547             AOP_TYPE(left) != AOP_DIR){
6548
6549     while(size--) {
6550       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6551       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6552       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6553       if(rIfx.condition)
6554         emitSKPNZ;
6555       else
6556         emitSKPZ;
6557       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6558       offset++;
6559       if(res_offset < res_size-1)
6560         res_offset++;
6561     }
6562       
6563   }else{
6564     /* right is a pointer reg need both a & b */
6565     while(size--) {
6566       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6567       if(strcmp(l,"b"))
6568         pic16_emitcode("mov","b,%s",l);
6569       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6570       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6571       offset++;
6572     }
6573   }
6574
6575   if(result && preserve_result)
6576     {
6577       int i;
6578       for(i = 0; i < AOP_SIZE(result); i++)
6579         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6580     }
6581
6582   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6583
6584   if(result && preserve_result)
6585     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6586
6587   if(!rIfx.condition)
6588     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6589
6590   pic16_emitpLabel(lbl->key);
6591
6592   if(result && preserve_result)
6593     {
6594       int i;
6595       for(i = 0; i < AOP_SIZE(result); i++)
6596         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6597
6598       pic16_emitpLabel(lbl_done->key);
6599    }
6600
6601   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6602
6603   if(ifx)
6604     ifx->generated = 1;
6605 }
6606 #endif
6607
6608 #if 0
6609 /*-----------------------------------------------------------------*/
6610 /* gencjne - compare and jump if not equal                         */
6611 /*-----------------------------------------------------------------*/
6612 static void gencjne(operand *left, operand *right, iCode *ifx)
6613 {
6614     symbol *tlbl  = newiTempLabel(NULL);
6615
6616     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6617     gencjneshort(left, right, lbl);
6618
6619     pic16_emitcode("mov","a,%s",one);
6620     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6621     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6622     pic16_emitcode("clr","a");
6623     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6624
6625     pic16_emitpLabel(lbl->key);
6626     pic16_emitpLabel(tlbl->key);
6627
6628 }
6629 #endif
6630
6631
6632 /*-----------------------------------------------------------------*/
6633 /* is_LitOp - check if operand has to be treated as literal        */
6634 /*-----------------------------------------------------------------*/
6635 static bool is_LitOp(operand *op)
6636 {
6637   return ((AOP_TYPE(op) == AOP_LIT)
6638       || ( (AOP_TYPE(op) == AOP_PCODE)
6639           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6640               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6641 }
6642
6643 /*-----------------------------------------------------------------*/
6644 /* is_LitAOp - check if operand has to be treated as literal        */
6645 /*-----------------------------------------------------------------*/
6646 static bool is_LitAOp(asmop *aop)
6647 {
6648   return ((aop->type == AOP_LIT)
6649       || ( (aop->type == AOP_PCODE)
6650           && ( (aop->aopu.pcop->type == PO_LITERAL)
6651               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6652 }
6653
6654
6655
6656 /*-----------------------------------------------------------------*/
6657 /* genCmpEq - generates code for equal to                          */
6658 /*-----------------------------------------------------------------*/
6659 static void genCmpEq (iCode *ic, iCode *ifx)
6660 {
6661   operand *left, *right, *result;
6662   symbol *falselbl = newiTempLabel(NULL);
6663   symbol *donelbl = newiTempLabel(NULL);
6664
6665   int preserve_result = 0;
6666   int generate_result = 0;
6667   int i=0;
6668
6669   FENTRY;
6670   
6671   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6672   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6673   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6674  
6675   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6676
6677   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6678     {
6679       werror(W_POSSBUG2, __FILE__, __LINE__);
6680       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6681       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6682       goto release;
6683     }
6684
6685   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6686     {
6687       operand *tmp = right ;
6688       right = left;
6689       left = tmp;
6690     }
6691
6692   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6693     preserve_result = 1;
6694
6695   if(result && AOP_SIZE(result))
6696     generate_result = 1;
6697
6698   if(generate_result && !preserve_result)
6699     {
6700       for(i = 0; i < AOP_SIZE(result); i++)
6701         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6702     }
6703
6704   for(i=0; i < AOP_SIZE(left); i++)
6705     {
6706       if(AOP_TYPE(left) != AOP_ACC)
6707         {
6708           if(is_LitOp(left))
6709             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6710           else
6711             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6712         }
6713       if(is_LitOp(right))
6714         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6715       else
6716         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6717
6718       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6719     }
6720
6721   // result == true
6722
6723   if(generate_result && preserve_result)
6724     {
6725       for(i = 0; i < AOP_SIZE(result); i++)
6726         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6727     }
6728
6729   if(generate_result)
6730     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6731
6732   if(generate_result && preserve_result)
6733     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6734
6735   if(ifx && IC_TRUE(ifx))
6736     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6737
6738   if(ifx && IC_FALSE(ifx))
6739     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6740
6741   pic16_emitpLabel(falselbl->key);
6742
6743   // result == false
6744
6745   if(ifx && IC_FALSE(ifx))
6746     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6747
6748   if(generate_result && preserve_result)
6749     {
6750       for(i = 0; i < AOP_SIZE(result); i++)
6751         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6752     }
6753
6754   pic16_emitpLabel(donelbl->key);
6755
6756   if(ifx)
6757     ifx->generated = 1;
6758
6759 release:
6760   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6761   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6762   pic16_freeAsmop(result,NULL,ic,TRUE);
6763
6764 }
6765
6766
6767 #if 0
6768 // old version kept for reference
6769
6770 /*-----------------------------------------------------------------*/
6771 /* genCmpEq - generates code for equal to                          */
6772 /*-----------------------------------------------------------------*/
6773 static void genCmpEq (iCode *ic, iCode *ifx)
6774 {
6775     operand *left, *right, *result;
6776     unsigned long lit = 0L;
6777     int size,offset=0;
6778     symbol *falselbl  = newiTempLabel(NULL);
6779
6780
6781     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6782
6783     if(ifx)
6784       DEBUGpic16_emitcode ("; ifx is non-null","");
6785     else
6786       DEBUGpic16_emitcode ("; ifx is null","");
6787
6788     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6789     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6790     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6791
6792     size = max(AOP_SIZE(left),AOP_SIZE(right));
6793
6794     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6795
6796     /* if literal, literal on the right or 
6797     if the right is in a pointer register and left 
6798     is not */
6799     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6800         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6801       operand *tmp = right ;
6802       right = left;
6803       left = tmp;
6804     }
6805
6806
6807     if(ifx && !AOP_SIZE(result)){
6808         symbol *tlbl;
6809         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6810         /* if they are both bit variables */
6811         if (AOP_TYPE(left) == AOP_CRY &&
6812             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6813                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6814             if(AOP_TYPE(right) == AOP_LIT){
6815                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6816                 if(lit == 0L){
6817                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6818                     pic16_emitcode("cpl","c");
6819                 } else if(lit == 1L) {
6820                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6821                 } else {
6822                     pic16_emitcode("clr","c");
6823                 }
6824                 /* AOP_TYPE(right) == AOP_CRY */
6825             } else {
6826                 symbol *lbl = newiTempLabel(NULL);
6827                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6828                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6829                 pic16_emitcode("cpl","c");
6830                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6831             }
6832             /* if true label then we jump if condition
6833             supplied is true */
6834             tlbl = newiTempLabel(NULL);
6835             if ( IC_TRUE(ifx) ) {
6836                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6837                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6838             } else {
6839                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6840                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6841             }
6842             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6843
6844                 {
6845                 /* left and right are both bit variables, result is carry */
6846                         resolvedIfx rIfx;
6847               
6848                         resolveIfx(&rIfx,ifx);
6849
6850                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6851                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6852                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6853                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6854                         genSkipz2(&rIfx,0);
6855                 }
6856         } else {
6857
6858                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6859
6860                         /* They're not both bit variables. Is the right a literal? */
6861                         if(AOP_TYPE(right) == AOP_LIT) {
6862                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6863             
6864                         switch(size) {
6865
6866                                 case 1:
6867                                         switch(lit & 0xff) {
6868                                                 case 1:
6869                                                                 if ( IC_TRUE(ifx) ) {
6870                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6871                                                                         emitSKPNZ;
6872                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6873                                                                 } else {
6874                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6875                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6876                                                                 }
6877                                                                 break;
6878                                                 case 0xff:
6879                                                                 if ( IC_TRUE(ifx) ) {
6880                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6881                                                                         emitSKPNZ;
6882                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6883                                                                 } else {
6884                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6885                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6886                                                                 }
6887                                                                 break;
6888                                                 default:
6889                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6890                                                                 if(lit)
6891                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6892                                                                 genSkip(ifx,'z');
6893                                         } // switch lit
6894
6895
6896                                         /* end of size == 1 */
6897                                         break;
6898               
6899                                 case 2:
6900                                         genc16bit2lit(left,lit,offset);
6901                                         genSkip(ifx,'z');
6902                                         break;
6903                                         /* end of size == 2 */
6904
6905                                 default:
6906                                         /* size is 4 */
6907                                         if(lit==0) {
6908                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6909                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6910                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6911                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6912                                                 genSkip(ifx,'z');
6913                                         } else {
6914                                                 /* search for patterns that can be optimized */
6915
6916                                                 genc16bit2lit(left,lit,0);
6917                                                 lit >>= 16;
6918                                                 if(lit) {
6919                                                                 if(IC_TRUE(ifx))
6920                                                                 emitSKPZ; // if hi word unequal
6921                                                                 else
6922                                                                 emitSKPNZ; // if hi word equal
6923                                                                 // fail early
6924                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6925                                                         genc16bit2lit(left,lit,2);
6926                                                         genSkip(ifx,'z');
6927                                                 } else {
6928                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6929                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6930                                                         genSkip(ifx,'z');
6931                                                 }
6932                                         }
6933                                                 pic16_emitpLabel(falselbl->key);
6934                                                 break;
6935
6936                         } // switch size
6937           
6938                         ifx->generated = 1;
6939                         goto release ;
6940             
6941
6942           } else if(AOP_TYPE(right) == AOP_CRY ) {
6943             /* we know the left is not a bit, but that the right is */
6944             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6945             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6946                       pic16_popGet(AOP(right),offset));
6947             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6948
6949             /* if the two are equal, then W will be 0 and the Z bit is set
6950              * we could test Z now, or go ahead and check the high order bytes if
6951              * the variable we're comparing is larger than a byte. */
6952
6953             while(--size)
6954               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6955
6956             if ( IC_TRUE(ifx) ) {
6957               emitSKPNZ;
6958               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6959               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6960             } else {
6961               emitSKPZ;
6962               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6963               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6964             }
6965
6966           } else {
6967             /* They're both variables that are larger than bits */
6968             int s = size;
6969
6970             tlbl = newiTempLabel(NULL);
6971
6972             while(size--) {
6973               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6974               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6975
6976               if ( IC_TRUE(ifx) ) {
6977                 if(size) {
6978                   emitSKPZ;
6979                 
6980                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6981
6982                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6983                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6984                 } else {
6985                   emitSKPNZ;
6986
6987                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6988
6989
6990                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6991                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6992                 }
6993               } else {
6994                 emitSKPZ;
6995
6996                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6997
6998                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6999                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7000               }
7001               offset++;
7002             }
7003             if(s>1 && IC_TRUE(ifx)) {
7004               pic16_emitpLabel(tlbl->key);
7005               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7006             }
7007           }
7008         }
7009         /* mark the icode as generated */
7010         ifx->generated = 1;
7011         goto release ;
7012     }
7013
7014     /* if they are both bit variables */
7015     if (AOP_TYPE(left) == AOP_CRY &&
7016         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7017         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7018         if(AOP_TYPE(right) == AOP_LIT){
7019             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7020             if(lit == 0L){
7021                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7022                 pic16_emitcode("cpl","c");
7023             } else if(lit == 1L) {
7024                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7025             } else {
7026                 pic16_emitcode("clr","c");
7027             }
7028             /* AOP_TYPE(right) == AOP_CRY */
7029         } else {
7030             symbol *lbl = newiTempLabel(NULL);
7031             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7032             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7033             pic16_emitcode("cpl","c");
7034             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7035         }
7036         /* c = 1 if egal */
7037         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7038             pic16_outBitC(result);
7039             goto release ;
7040         }
7041         if (ifx) {
7042             genIfxJump (ifx,"c");
7043             goto release ;
7044         }
7045         /* if the result is used in an arithmetic operation
7046         then put the result in place */
7047         pic16_outBitC(result);
7048     } else {
7049       
7050       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7051       gencjne(left,right,result,ifx);
7052 /*
7053       if(ifx) 
7054         gencjne(left,right,newiTempLabel(NULL));
7055       else {
7056         if(IC_TRUE(ifx)->key)
7057           gencjne(left,right,IC_TRUE(ifx)->key);
7058         else
7059           gencjne(left,right,IC_FALSE(ifx)->key);
7060         ifx->generated = 1;
7061         goto release ;
7062       }
7063       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7064         pic16_aopPut(AOP(result),"a",0);
7065         goto release ;
7066       }
7067
7068       if (ifx) {
7069         genIfxJump (ifx,"a");
7070         goto release ;
7071       }
7072 */
7073       /* if the result is used in an arithmetic operation
7074          then put the result in place */
7075 /*
7076       if (AOP_TYPE(result) != AOP_CRY) 
7077         pic16_outAcc(result);
7078 */
7079       /* leave the result in acc */
7080     }
7081
7082 release:
7083     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7084     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7085     pic16_freeAsmop(result,NULL,ic,TRUE);
7086 }
7087 #endif
7088
7089 /*-----------------------------------------------------------------*/
7090 /* ifxForOp - returns the icode containing the ifx for operand     */
7091 /*-----------------------------------------------------------------*/
7092 static iCode *ifxForOp ( operand *op, iCode *ic )
7093 {
7094   FENTRY2;
7095
7096     /* if true symbol then needs to be assigned */
7097     if (IS_TRUE_SYMOP(op))
7098         return NULL ;
7099
7100     /* if this has register type condition and
7101     the next instruction is ifx with the same operand
7102     and live to of the operand is upto the ifx only then */
7103     if (ic->next
7104         && ic->next->op == IFX
7105         && IC_COND(ic->next)->key == op->key
7106         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7107         ) {
7108                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7109           return ic->next;
7110     }
7111
7112     if (ic->next &&
7113         ic->next->op == IFX &&
7114         IC_COND(ic->next)->key == op->key) {
7115       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7116       return ic->next;
7117     }
7118
7119     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7120     if (ic->next &&
7121         ic->next->op == IFX)
7122       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7123
7124     if (ic->next &&
7125         ic->next->op == IFX &&
7126         IC_COND(ic->next)->key == op->key) {
7127       DEBUGpic16_emitcode ("; "," key is okay");
7128       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7129                            OP_SYMBOL(op)->liveTo,
7130                            ic->next->seq);
7131     }
7132
7133 #if 0
7134     /* the code below is completely untested
7135      * it just allows ulong2fs.c compile -- VR */
7136          
7137     ic = ic->next;
7138     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7139                                         __FILE__, __FUNCTION__, __LINE__);
7140         
7141     /* if this has register type condition and
7142     the next instruction is ifx with the same operand
7143     and live to of the operand is upto the ifx only then */
7144     if (ic->next &&
7145         ic->next->op == IFX &&
7146         IC_COND(ic->next)->key == op->key &&
7147         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7148         return ic->next;
7149
7150     if (ic->next &&
7151         ic->next->op == IFX &&
7152         IC_COND(ic->next)->key == op->key) {
7153       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7154       return ic->next;
7155     }
7156
7157     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7158                                         __FILE__, __FUNCTION__, __LINE__);
7159
7160 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7161 #endif
7162
7163     return NULL;
7164 }
7165 /*-----------------------------------------------------------------*/
7166 /* genAndOp - for && operation                                     */
7167 /*-----------------------------------------------------------------*/
7168 static void genAndOp (iCode *ic)
7169 {
7170   operand *left,*right, *result;
7171 /*     symbol *tlbl; */
7172
7173     FENTRY;
7174
7175     /* note here that && operations that are in an
7176     if statement are taken away by backPatchLabels
7177     only those used in arthmetic operations remain */
7178     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7179     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7180     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7181
7182     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7183
7184     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7185     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7186     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7187
7188     /* if both are bit variables */
7189 /*     if (AOP_TYPE(left) == AOP_CRY && */
7190 /*         AOP_TYPE(right) == AOP_CRY ) { */
7191 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7192 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7193 /*         pic16_outBitC(result); */
7194 /*     } else { */
7195 /*         tlbl = newiTempLabel(NULL); */
7196 /*         pic16_toBoolean(left);     */
7197 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7198 /*         pic16_toBoolean(right); */
7199 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7200 /*         pic16_outBitAcc(result); */
7201 /*     } */
7202
7203     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7204     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7205     pic16_freeAsmop(result,NULL,ic,TRUE);
7206 }
7207
7208
7209 /*-----------------------------------------------------------------*/
7210 /* genOrOp - for || operation                                      */
7211 /*-----------------------------------------------------------------*/
7212 /*
7213   tsd pic port -
7214   modified this code, but it doesn't appear to ever get called
7215 */
7216
7217 static void genOrOp (iCode *ic)
7218 {
7219   operand *left,*right, *result;
7220   symbol *tlbl;
7221
7222     FENTRY;  
7223
7224   /* note here that || operations that are in an
7225     if statement are taken away by backPatchLabels
7226     only those used in arthmetic operations remain */
7227     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7228     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7229     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7230
7231     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7232
7233     /* if both are bit variables */
7234     if (AOP_TYPE(left) == AOP_CRY &&
7235         AOP_TYPE(right) == AOP_CRY ) {
7236       pic16_emitcode("clrc","");
7237       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7238                AOP(left)->aopu.aop_dir,
7239                AOP(left)->aopu.aop_dir);
7240       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7241                AOP(right)->aopu.aop_dir,
7242                AOP(right)->aopu.aop_dir);
7243       pic16_emitcode("setc","");
7244
7245     } else {
7246         tlbl = newiTempLabel(NULL);
7247         pic16_toBoolean(left);
7248         emitSKPZ;
7249         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7250         pic16_toBoolean(right);
7251         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7252
7253         pic16_outBitAcc(result);
7254     }
7255
7256     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7257     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7258     pic16_freeAsmop(result,NULL,ic,TRUE);            
7259 }
7260
7261 /*-----------------------------------------------------------------*/
7262 /* isLiteralBit - test if lit == 2^n                               */
7263 /*-----------------------------------------------------------------*/
7264 static int isLiteralBit(unsigned long lit)
7265 {
7266     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7267     0x100L,0x200L,0x400L,0x800L,
7268     0x1000L,0x2000L,0x4000L,0x8000L,
7269     0x10000L,0x20000L,0x40000L,0x80000L,
7270     0x100000L,0x200000L,0x400000L,0x800000L,
7271     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7272     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7273     int idx;
7274     
7275     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7276     for(idx = 0; idx < 32; idx++)
7277         if(lit == pw[idx])
7278             return idx+1;
7279     return 0;
7280 }
7281
7282 /*-----------------------------------------------------------------*/
7283 /* continueIfTrue -                                                */
7284 /*-----------------------------------------------------------------*/
7285 static void continueIfTrue (iCode *ic)
7286 {
7287   FENTRY;
7288   if(IC_TRUE(ic))
7289     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7290   ic->generated = 1;
7291 }
7292
7293 /*-----------------------------------------------------------------*/
7294 /* jmpIfTrue -                                                     */
7295 /*-----------------------------------------------------------------*/
7296 static void jumpIfTrue (iCode *ic)
7297 {
7298   FENTRY;
7299   if(!IC_TRUE(ic))
7300     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7301   ic->generated = 1;
7302 }
7303
7304 /*-----------------------------------------------------------------*/
7305 /* jmpTrueOrFalse -                                                */
7306 /*-----------------------------------------------------------------*/
7307 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7308 {
7309   // ugly but optimized by peephole
7310   FENTRY;
7311   if(IC_TRUE(ic)){
7312     symbol *nlbl = newiTempLabel(NULL);
7313       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7314       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7315       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7316       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7317   } else {
7318     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7319     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7320   }
7321   ic->generated = 1;
7322 }
7323
7324 /*-----------------------------------------------------------------*/
7325 /* genAnd  - code for and                                          */
7326 /*-----------------------------------------------------------------*/
7327 static void genAnd (iCode *ic, iCode *ifx)
7328 {
7329   operand *left, *right, *result;
7330   int size, offset=0;  
7331   unsigned long lit = 0L;
7332   int bytelit = 0;
7333   resolvedIfx rIfx;
7334
7335     FENTRY;
7336     
7337   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7338   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7339   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7340
7341   resolveIfx(&rIfx,ifx);
7342
7343   /* if left is a literal & right is not then exchange them */
7344   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7345       AOP_NEEDSACC(left)) {
7346     operand *tmp = right ;
7347     right = left;
7348     left = tmp;
7349   }
7350
7351   /* if result = right then exchange them */
7352   if(pic16_sameRegs(AOP(result),AOP(right))){
7353     operand *tmp = right ;
7354     right = left;
7355     left = tmp;
7356   }
7357
7358   /* if right is bit then exchange them */
7359   if (AOP_TYPE(right) == AOP_CRY &&
7360       AOP_TYPE(left) != AOP_CRY){
7361     operand *tmp = right ;
7362     right = left;
7363     left = tmp;
7364   }
7365   if(AOP_TYPE(right) == AOP_LIT)
7366     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7367
7368   size = AOP_SIZE(result);
7369
7370   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7371
7372   // if(bit & yy)
7373   // result = bit & yy;
7374   if (AOP_TYPE(left) == AOP_CRY){
7375     // c = bit & literal;
7376     if(AOP_TYPE(right) == AOP_LIT){
7377       if(lit & 1) {
7378         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7379           // no change
7380           goto release;
7381         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7382       } else {
7383         // bit(result) = 0;
7384         if(size && (AOP_TYPE(result) == AOP_CRY)){
7385           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7386           goto release;
7387         }
7388         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7389           jumpIfTrue(ifx);
7390           goto release;
7391         }
7392         pic16_emitcode("clr","c");
7393       }
7394     } else {
7395       if (AOP_TYPE(right) == AOP_CRY){
7396         // c = bit & bit;
7397         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7398         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7399       } else {
7400         // c = bit & val;
7401         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7402         // c = lsb
7403         pic16_emitcode("rrc","a");
7404         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7405       }
7406     }
7407     // bit = c
7408     // val = c
7409     if(size)
7410       pic16_outBitC(result);
7411     // if(bit & ...)
7412     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7413       genIfxJump(ifx, "c");           
7414     goto release ;
7415   }
7416
7417   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7418   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7419   if((AOP_TYPE(right) == AOP_LIT) &&
7420      (AOP_TYPE(result) == AOP_CRY) &&
7421      (AOP_TYPE(left) != AOP_CRY)){
7422     int posbit = isLiteralBit(lit);
7423     /* left &  2^n */
7424     if(posbit){
7425       posbit--;
7426       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7427       // bit = left & 2^n
7428       if(size)
7429         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7430       // if(left &  2^n)
7431       else{
7432         if(ifx){
7433 /*
7434           if(IC_TRUE(ifx)) {
7435             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7436             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7437           } else {
7438             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7439             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7440           }
7441 */
7442         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7443         size = AOP_SIZE(left);
7444
7445         {
7446           int bp = posbit, ofs=0;
7447           
7448             while(bp > 7) {
7449               bp -= 8;
7450               ofs++;
7451             }
7452         
7453           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7454                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7455
7456         }
7457 /*
7458           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7459                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7460 */
7461           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7462           
7463           ifx->generated = 1;
7464         }
7465         goto release;
7466       }
7467     } else {
7468       symbol *tlbl = newiTempLabel(NULL);
7469       int sizel = AOP_SIZE(left);
7470
7471       if(size)
7472         emitSETC;
7473
7474       while(sizel--) {
7475         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7476
7477           /* patch provided by Aaron Colwell */
7478           if((posbit = isLiteralBit(bytelit)) != 0) {
7479               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7480                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7481                                                 (posbit-1),0, PO_GPR_REGISTER));
7482
7483               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7484 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7485           } else {
7486               if (bytelit == 0xff) {
7487                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7488                    * a peephole could optimize it out -- VR */
7489                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7490               } else {
7491                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7492                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7493               }
7494
7495               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7496                             pic16_popGetLabel(tlbl->key));
7497           }
7498         
7499 #if 0
7500           /* old code, left here for reference -- VR 09/2004 */
7501           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7502           // byte ==  2^n ?
7503           if((posbit = isLiteralBit(bytelit)) != 0)
7504             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7505           else{
7506             if(bytelit != 0x0FFL)
7507               pic16_emitcode("anl","a,%s",
7508                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7509             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7510           }
7511 #endif
7512         }
7513         offset++;
7514       }
7515       // bit = left & literal
7516       if(size) {
7517         emitCLRC;
7518         pic16_emitpLabel(tlbl->key);
7519       }
7520       // if(left & literal)
7521       else {
7522         if(ifx) {
7523           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7524           ifx->generated = 1;
7525         }
7526         pic16_emitpLabel(tlbl->key);
7527         goto release;
7528       }
7529     }
7530
7531     pic16_outBitC(result);
7532     goto release ;
7533   }
7534
7535   /* if left is same as result */
7536   if(pic16_sameRegs(AOP(result),AOP(left))){
7537     int know_W = -1;
7538     for(;size--; offset++,lit>>=8) {
7539       if(AOP_TYPE(right) == AOP_LIT){
7540         switch(lit & 0xff) {
7541         case 0x00:
7542           /*  and'ing with 0 has clears the result */
7543 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7544           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7545           break;
7546         case 0xff:
7547           /* and'ing with 0xff is a nop when the result and left are the same */
7548           break;
7549
7550         default:
7551           {
7552             int p = pic16_my_powof2( (~lit) & 0xff );
7553             if(p>=0) {
7554               /* only one bit is set in the literal, so use a bcf instruction */
7555 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7556               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7557
7558             } else {
7559               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7560               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7561               if(know_W != (lit&0xff))
7562                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7563               know_W = lit &0xff;
7564               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7565             }
7566           }    
7567         }
7568       } else {
7569         if (AOP_TYPE(left) == AOP_ACC) {
7570           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7571         } else {                    
7572           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7573           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7574
7575         }
7576       }
7577     }
7578
7579   } else {
7580     // left & result in different registers
7581     if(AOP_TYPE(result) == AOP_CRY){
7582       // result = bit
7583       // if(size), result in bit
7584       // if(!size && ifx), conditional oper: if(left & right)
7585       symbol *tlbl = newiTempLabel(NULL);
7586       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7587       if(size)
7588         pic16_emitcode("setb","c");
7589       while(sizer--){
7590         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7591         pic16_emitcode("anl","a,%s",
7592                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7593         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7594         offset++;
7595       }
7596       if(size){
7597         CLRC;
7598         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7599         pic16_outBitC(result);
7600       } else if(ifx)
7601         jmpTrueOrFalse(ifx, tlbl);
7602     } else {
7603       for(;(size--);offset++) {
7604         // normal case
7605         // result = left & right
7606         if(AOP_TYPE(right) == AOP_LIT){
7607           int t = (lit >> (offset*8)) & 0x0FFL;
7608           switch(t) { 
7609           case 0x00:
7610             pic16_emitcode("clrf","%s",
7611                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7612             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7613             break;
7614           case 0xff:
7615             pic16_emitcode("movf","%s,w",
7616                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7617             pic16_emitcode("movwf","%s",
7618                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7619             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7620             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7621             break;
7622           default:
7623             pic16_emitcode("movlw","0x%x",t);
7624             pic16_emitcode("andwf","%s,w",
7625                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7626             pic16_emitcode("movwf","%s",
7627                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7628               
7629             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7630             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7631             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7632           }
7633           continue;
7634         }
7635
7636         if (AOP_TYPE(left) == AOP_ACC) {
7637           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7638           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7639         } else {
7640           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7641           pic16_emitcode("andwf","%s,w",
7642                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7643           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7644           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7645         }
7646         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7647         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7648       }
7649     }
7650   }
7651
7652   release :
7653     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7654   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7655   pic16_freeAsmop(result,NULL,ic,TRUE);     
7656 }
7657
7658 /*-----------------------------------------------------------------*/
7659 /* genOr  - code for or                                            */
7660 /*-----------------------------------------------------------------*/
7661 static void genOr (iCode *ic, iCode *ifx)
7662 {
7663     operand *left, *right, *result;
7664     int size, offset=0;
7665     unsigned long lit = 0L;
7666
7667     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7668
7669     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7670     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7671     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7672
7673     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7674
7675     /* if left is a literal & right is not then exchange them */
7676     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7677         AOP_NEEDSACC(left)) {
7678         operand *tmp = right ;
7679         right = left;
7680         left = tmp;
7681     }
7682
7683     /* if result = right then exchange them */
7684     if(pic16_sameRegs(AOP(result),AOP(right))){
7685         operand *tmp = right ;
7686         right = left;
7687         left = tmp;
7688     }
7689
7690     /* if right is bit then exchange them */
7691     if (AOP_TYPE(right) == AOP_CRY &&
7692         AOP_TYPE(left) != AOP_CRY){
7693         operand *tmp = right ;
7694         right = left;
7695         left = tmp;
7696     }
7697
7698     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7699
7700     if(AOP_TYPE(right) == AOP_LIT)
7701         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7702
7703     size = AOP_SIZE(result);
7704
7705     // if(bit | yy)
7706     // xx = bit | yy;
7707     if (AOP_TYPE(left) == AOP_CRY){
7708         if(AOP_TYPE(right) == AOP_LIT){
7709             // c = bit & literal;
7710             if(lit){
7711                 // lit != 0 => result = 1
7712                 if(AOP_TYPE(result) == AOP_CRY){
7713                   if(size)
7714                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7715                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7716                   //     AOP(result)->aopu.aop_dir,
7717                   //     AOP(result)->aopu.aop_dir);
7718                     else if(ifx)
7719                         continueIfTrue(ifx);
7720                     goto release;
7721                 }
7722             } else {
7723                 // lit == 0 => result = left
7724                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7725                     goto release;
7726                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7727             }
7728         } else {
7729             if (AOP_TYPE(right) == AOP_CRY){
7730               if(pic16_sameRegs(AOP(result),AOP(left))){
7731                 // c = bit | bit;
7732                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7733                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7734                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7735
7736                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7737                          AOP(result)->aopu.aop_dir,
7738                          AOP(result)->aopu.aop_dir);
7739                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7740                          AOP(right)->aopu.aop_dir,
7741                          AOP(right)->aopu.aop_dir);
7742                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7743                          AOP(result)->aopu.aop_dir,
7744                          AOP(result)->aopu.aop_dir);
7745               } else {
7746                 if( AOP_TYPE(result) == AOP_ACC) {
7747                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7748                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7749                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7750                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7751
7752                 } else {
7753
7754                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7755                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7756                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7757                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7758
7759                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7760                                  AOP(result)->aopu.aop_dir,
7761                                  AOP(result)->aopu.aop_dir);
7762                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7763                                  AOP(right)->aopu.aop_dir,
7764                                  AOP(right)->aopu.aop_dir);
7765                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7766                                  AOP(left)->aopu.aop_dir,
7767                                  AOP(left)->aopu.aop_dir);
7768                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7769                                  AOP(result)->aopu.aop_dir,
7770                                  AOP(result)->aopu.aop_dir);
7771                 }
7772               }
7773             } else {
7774                 // c = bit | val;
7775                 symbol *tlbl = newiTempLabel(NULL);
7776                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7777
7778
7779                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7780                 if( AOP_TYPE(right) == AOP_ACC) {
7781                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7782                   emitSKPNZ;
7783                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7784                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7785                 }
7786
7787
7788
7789                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7790                     pic16_emitcode(";XXX setb","c");
7791                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7792                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7793                 pic16_toBoolean(right);
7794                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7795                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7796                     jmpTrueOrFalse(ifx, tlbl);
7797                     goto release;
7798                 } else {
7799                     CLRC;
7800                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7801                 }
7802             }
7803         }
7804         // bit = c
7805         // val = c
7806         if(size)
7807             pic16_outBitC(result);
7808         // if(bit | ...)
7809         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7810             genIfxJump(ifx, "c");           
7811         goto release ;
7812     }
7813
7814     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7815     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7816     if((AOP_TYPE(right) == AOP_LIT) &&
7817        (AOP_TYPE(result) == AOP_CRY) &&
7818        (AOP_TYPE(left) != AOP_CRY)){
7819         if(lit){
7820           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7821             // result = 1
7822             if(size)
7823                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7824             else 
7825                 continueIfTrue(ifx);
7826             goto release;
7827         } else {
7828           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7829             // lit = 0, result = boolean(left)
7830             if(size)
7831                 pic16_emitcode(";XXX setb","c");
7832             pic16_toBoolean(right);
7833             if(size){
7834                 symbol *tlbl = newiTempLabel(NULL);
7835                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7836                 CLRC;
7837                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7838             } else {
7839                 genIfxJump (ifx,"a");
7840                 goto release;
7841             }
7842         }
7843         pic16_outBitC(result);
7844         goto release ;
7845     }
7846
7847     /* if left is same as result */
7848     if(pic16_sameRegs(AOP(result),AOP(left))){
7849       int know_W = -1;
7850       for(;size--; offset++,lit>>=8) {
7851         if(AOP_TYPE(right) == AOP_LIT){
7852           if((lit & 0xff) == 0)
7853             /*  or'ing with 0 has no effect */
7854             continue;
7855           else {
7856             int p = pic16_my_powof2(lit & 0xff);
7857             if(p>=0) {
7858               /* only one bit is set in the literal, so use a bsf instruction */
7859               pic16_emitpcode(POC_BSF,
7860                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7861             } else {
7862               if(know_W != (lit & 0xff))
7863                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7864               know_W = lit & 0xff;
7865               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7866             }
7867                     
7868           }
7869         } else {
7870           if (AOP_TYPE(left) == AOP_ACC) {
7871             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7872             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7873           } else {                  
7874             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7875             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7876
7877             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7878             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7879
7880           }
7881         }
7882       }
7883     } else {
7884         // left & result in different registers
7885         if(AOP_TYPE(result) == AOP_CRY){
7886             // result = bit
7887             // if(size), result in bit
7888             // if(!size && ifx), conditional oper: if(left | right)
7889             symbol *tlbl = newiTempLabel(NULL);
7890             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7891             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7892
7893
7894             if(size)
7895                 pic16_emitcode(";XXX setb","c");
7896             while(sizer--){
7897                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7898                 pic16_emitcode(";XXX orl","a,%s",
7899                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7900                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7901                 offset++;
7902             }
7903             if(size){
7904                 CLRC;
7905                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7906                 pic16_outBitC(result);
7907             } else if(ifx)
7908                 jmpTrueOrFalse(ifx, tlbl);
7909         } else for(;(size--);offset++){
7910           // normal case
7911           // result = left & right
7912           if(AOP_TYPE(right) == AOP_LIT){
7913             int t = (lit >> (offset*8)) & 0x0FFL;
7914             switch(t) { 
7915             case 0x00:
7916               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7917               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7918
7919               pic16_emitcode("movf","%s,w",
7920                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7921               pic16_emitcode("movwf","%s",
7922                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7923               break;
7924             default:
7925               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7926               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7927               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7928
7929               pic16_emitcode("movlw","0x%x",t);
7930               pic16_emitcode("iorwf","%s,w",
7931                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7932               pic16_emitcode("movwf","%s",
7933                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7934               
7935             }
7936             continue;
7937           }
7938
7939           // faster than result <- left, anl result,right
7940           // and better if result is SFR
7941           if (AOP_TYPE(left) == AOP_ACC) {
7942             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7943             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7944           } else {
7945             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7946             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7947
7948             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7949             pic16_emitcode("iorwf","%s,w",
7950                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7951           }
7952           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7953           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7954         }
7955     }
7956
7957 release :
7958     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7959     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7960     pic16_freeAsmop(result,NULL,ic,TRUE);     
7961 }
7962
7963 /*-----------------------------------------------------------------*/
7964 /* genXor - code for xclusive or                                   */
7965 /*-----------------------------------------------------------------*/
7966 static void genXor (iCode *ic, iCode *ifx)
7967 {
7968   operand *left, *right, *result;
7969   int size, offset=0;
7970   unsigned long lit = 0L;
7971
7972   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7973
7974   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7975   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7976   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7977
7978   /* if left is a literal & right is not ||
7979      if left needs acc & right does not */
7980   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7981       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7982     operand *tmp = right ;
7983     right = left;
7984     left = tmp;
7985   }
7986
7987   /* if result = right then exchange them */
7988   if(pic16_sameRegs(AOP(result),AOP(right))){
7989     operand *tmp = right ;
7990     right = left;
7991     left = tmp;
7992   }
7993
7994   /* if right is bit then exchange them */
7995   if (AOP_TYPE(right) == AOP_CRY &&
7996       AOP_TYPE(left) != AOP_CRY){
7997     operand *tmp = right ;
7998     right = left;
7999     left = tmp;
8000   }
8001   if(AOP_TYPE(right) == AOP_LIT)
8002     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8003
8004   size = AOP_SIZE(result);
8005
8006   // if(bit ^ yy)
8007   // xx = bit ^ yy;
8008   if (AOP_TYPE(left) == AOP_CRY){
8009     if(AOP_TYPE(right) == AOP_LIT){
8010       // c = bit & literal;
8011       if(lit>>1){
8012         // lit>>1  != 0 => result = 1
8013         if(AOP_TYPE(result) == AOP_CRY){
8014           if(size)
8015             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8016             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8017           else if(ifx)
8018             continueIfTrue(ifx);
8019           goto release;
8020         }
8021         pic16_emitcode("setb","c");
8022       } else{
8023         // lit == (0 or 1)
8024         if(lit == 0){
8025           // lit == 0, result = left
8026           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8027             goto release;
8028           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8029         } else{
8030           // lit == 1, result = not(left)
8031           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8032             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8033             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8034             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8035             goto release;
8036           } else {
8037             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8038             pic16_emitcode("cpl","c");
8039           }
8040         }
8041       }
8042
8043     } else {
8044       // right != literal
8045       symbol *tlbl = newiTempLabel(NULL);
8046       if (AOP_TYPE(right) == AOP_CRY){
8047         // c = bit ^ bit;
8048         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8049       }
8050       else{
8051         int sizer = AOP_SIZE(right);
8052         // c = bit ^ val
8053         // if val>>1 != 0, result = 1
8054         pic16_emitcode("setb","c");
8055         while(sizer){
8056           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8057           if(sizer == 1)
8058             // test the msb of the lsb
8059             pic16_emitcode("anl","a,#0xfe");
8060           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8061           sizer--;
8062         }
8063         // val = (0,1)
8064         pic16_emitcode("rrc","a");
8065       }
8066       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8067       pic16_emitcode("cpl","c");
8068       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8069     }
8070     // bit = c
8071     // val = c
8072     if(size)
8073       pic16_outBitC(result);
8074     // if(bit | ...)
8075     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8076       genIfxJump(ifx, "c");           
8077     goto release ;
8078   }
8079
8080   if(pic16_sameRegs(AOP(result),AOP(left))){
8081     /* if left is same as result */
8082     for(;size--; offset++) {
8083       if(AOP_TYPE(right) == AOP_LIT){
8084         int t  = (lit >> (offset*8)) & 0x0FFL;
8085         if(t == 0x00L)
8086           continue;
8087         else
8088           if (IS_AOP_PREG(left)) {
8089             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8090             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8091             pic16_aopPut(AOP(result),"a",offset);
8092           } else {
8093             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8094             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8095             pic16_emitcode("xrl","%s,%s",
8096                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8097                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8098           }
8099       } else {
8100         if (AOP_TYPE(left) == AOP_ACC)
8101           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8102         else {
8103           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8104           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8105 /*
8106           if (IS_AOP_PREG(left)) {
8107             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8108             pic16_aopPut(AOP(result),"a",offset);
8109           } else
8110             pic16_emitcode("xrl","%s,a",
8111                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8112 */
8113         }
8114       }
8115     }
8116   } else {
8117     // left & result in different registers
8118     if(AOP_TYPE(result) == AOP_CRY){
8119       // result = bit
8120       // if(size), result in bit
8121       // if(!size && ifx), conditional oper: if(left ^ right)
8122       symbol *tlbl = newiTempLabel(NULL);
8123       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8124       if(size)
8125         pic16_emitcode("setb","c");
8126       while(sizer--){
8127         if((AOP_TYPE(right) == AOP_LIT) &&
8128            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8129           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8130         } else {
8131           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8132           pic16_emitcode("xrl","a,%s",
8133                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8134         }
8135         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8136         offset++;
8137       }
8138       if(size){
8139         CLRC;
8140         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8141         pic16_outBitC(result);
8142       } else if(ifx)
8143         jmpTrueOrFalse(ifx, tlbl);
8144     } else for(;(size--);offset++){
8145       // normal case
8146       // result = left & right
8147       if(AOP_TYPE(right) == AOP_LIT){
8148         int t = (lit >> (offset*8)) & 0x0FFL;
8149         switch(t) { 
8150         case 0x00:
8151           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8152           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8153           pic16_emitcode("movf","%s,w",
8154                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8155           pic16_emitcode("movwf","%s",
8156                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8157           break;
8158         case 0xff:
8159           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8160           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8161           pic16_emitcode("comf","%s,w",
8162                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8163           pic16_emitcode("movwf","%s",
8164                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8165           break;
8166         default:
8167           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8168           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8169           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8170           pic16_emitcode("movlw","0x%x",t);
8171           pic16_emitcode("xorwf","%s,w",
8172                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8173           pic16_emitcode("movwf","%s",
8174                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8175
8176         }
8177         continue;
8178       }
8179
8180       // faster than result <- left, anl result,right
8181       // and better if result is SFR
8182       if (AOP_TYPE(left) == AOP_ACC) {
8183         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8184         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8185       } else {
8186         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8187         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8188         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8189         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8190       }
8191       if ( AOP_TYPE(result) != AOP_ACC){
8192         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8193         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8194       }
8195     }
8196   }
8197
8198   release :
8199     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8200   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8201   pic16_freeAsmop(result,NULL,ic,TRUE);     
8202 }
8203
8204 /*-----------------------------------------------------------------*/
8205 /* genInline - write the inline code out                           */
8206 /*-----------------------------------------------------------------*/
8207 static void genInline (iCode *ic)
8208 {
8209   char *buffer, *bp, *bp1;
8210     
8211         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8212
8213         _G.inLine += (!options.asmpeep);
8214
8215         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8216         strcpy(buffer,IC_INLINE(ic));
8217
8218 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
8219
8220         /* emit each line as a code */
8221         while (*bp) {
8222                 if (*bp == '\n') {
8223                         *bp++ = '\0';
8224
8225                         if(*bp1)
8226                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8227                         bp1 = bp;
8228                 } else {
8229                         if (*bp == ':') {
8230                                 bp++;
8231                                 *bp = '\0';
8232                                 bp++;
8233
8234                                 /* print label, use this special format with NULL directive
8235                                  * to denote that the argument should not be indented with tab */
8236                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8237                                 bp1 = bp;
8238                         } else
8239                                 bp++;
8240                 }
8241         }
8242
8243         if ((bp1 != bp) && *bp1)
8244                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8245
8246
8247     Safe_free(buffer);
8248
8249     _G.inLine -= (!options.asmpeep);
8250 }
8251
8252 /*-----------------------------------------------------------------*/
8253 /* genRRC - rotate right with carry                                */
8254 /*-----------------------------------------------------------------*/
8255 static void genRRC (iCode *ic)
8256 {
8257   operand *left , *result ;
8258   int size, offset = 0, same;
8259
8260   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8261
8262   /* rotate right with carry */
8263   left = IC_LEFT(ic);
8264   result=IC_RESULT(ic);
8265   pic16_aopOp (left,ic,FALSE);
8266   pic16_aopOp (result,ic,FALSE);
8267
8268   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8269
8270   same = pic16_sameRegs(AOP(result),AOP(left));
8271
8272   size = AOP_SIZE(result);    
8273
8274   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8275
8276   /* get the lsb and put it into the carry */
8277   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8278
8279   offset = 0 ;
8280
8281   while(size--) {
8282
8283     if(same) {
8284       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8285     } else {
8286       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8287       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8288     }
8289
8290     offset++;
8291   }
8292
8293   pic16_freeAsmop(left,NULL,ic,TRUE);
8294   pic16_freeAsmop(result,NULL,ic,TRUE);
8295 }
8296
8297 /*-----------------------------------------------------------------*/
8298 /* genRLC - generate code for rotate left with carry               */
8299 /*-----------------------------------------------------------------*/
8300 static void genRLC (iCode *ic)
8301 {    
8302   operand *left , *result ;
8303   int size, offset = 0;
8304   int same;
8305
8306   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8307   /* rotate right with carry */
8308   left = IC_LEFT(ic);
8309   result=IC_RESULT(ic);
8310   pic16_aopOp (left,ic,FALSE);
8311   pic16_aopOp (result,ic,FALSE);
8312
8313   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8314
8315   same = pic16_sameRegs(AOP(result),AOP(left));
8316
8317   /* move it to the result */
8318   size = AOP_SIZE(result);    
8319
8320   /* get the msb and put it into the carry */
8321   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8322
8323   offset = 0 ;
8324
8325   while(size--) {
8326
8327     if(same) {
8328       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8329     } else {
8330       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8331       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8332     }
8333
8334     offset++;
8335   }
8336
8337
8338   pic16_freeAsmop(left,NULL,ic,TRUE);
8339   pic16_freeAsmop(result,NULL,ic,TRUE);
8340 }
8341
8342
8343 /* gpasm can get the highest order bit with HIGH/UPPER
8344  * so the following probably is not needed -- VR */
8345  
8346 /*-----------------------------------------------------------------*/
8347 /* genGetHbit - generates code get highest order bit               */
8348 /*-----------------------------------------------------------------*/
8349 static void genGetHbit (iCode *ic)
8350 {
8351     operand *left, *result;
8352     left = IC_LEFT(ic);
8353     result=IC_RESULT(ic);
8354     pic16_aopOp (left,ic,FALSE);
8355     pic16_aopOp (result,ic,FALSE);
8356
8357     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8358     /* get the highest order byte into a */
8359     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8360     if(AOP_TYPE(result) == AOP_CRY){
8361         pic16_emitcode("rlc","a");
8362         pic16_outBitC(result);
8363     }
8364     else{
8365         pic16_emitcode("rl","a");
8366         pic16_emitcode("anl","a,#0x01");
8367         pic16_outAcc(result);
8368     }
8369
8370
8371     pic16_freeAsmop(left,NULL,ic,TRUE);
8372     pic16_freeAsmop(result,NULL,ic,TRUE);
8373 }
8374
8375 #if 0
8376 /*-----------------------------------------------------------------*/
8377 /* AccRol - rotate left accumulator by known count                 */
8378 /*-----------------------------------------------------------------*/
8379 static void AccRol (int shCount)
8380 {
8381     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8382     shCount &= 0x0007;              // shCount : 0..7
8383     switch(shCount){
8384         case 0 :
8385             break;
8386         case 1 :
8387             pic16_emitcode("rl","a");
8388             break;
8389         case 2 :
8390             pic16_emitcode("rl","a");
8391             pic16_emitcode("rl","a");
8392             break;
8393         case 3 :
8394             pic16_emitcode("swap","a");
8395             pic16_emitcode("rr","a");
8396             break;
8397         case 4 :
8398             pic16_emitcode("swap","a");
8399             break;
8400         case 5 :
8401             pic16_emitcode("swap","a");
8402             pic16_emitcode("rl","a");
8403             break;
8404         case 6 :
8405             pic16_emitcode("rr","a");
8406             pic16_emitcode("rr","a");
8407             break;
8408         case 7 :
8409             pic16_emitcode("rr","a");
8410             break;
8411     }
8412 }
8413 #endif
8414
8415 /*-----------------------------------------------------------------*/
8416 /* AccLsh - left shift accumulator by known count                  */
8417 /*-----------------------------------------------------------------*/
8418 static void AccLsh (int shCount)
8419 {
8420         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8421         switch(shCount){
8422                 case 0 :
8423                         return;
8424                         break;
8425                 case 1 :
8426                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8427                         break;
8428                 case 2 :
8429                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8430                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8431                         break;
8432                 case 3 :
8433                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8434                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8435                         break;
8436                 case 4 :
8437                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8438                         break;
8439                 case 5 :
8440                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8441                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8442                         break;
8443                 case 6 :
8444                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8445                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8446                         break;
8447                 case 7 :
8448                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8449                         break;
8450         }
8451
8452         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8453 }
8454
8455 /*-----------------------------------------------------------------*/
8456 /* AccRsh - right shift accumulator by known count                 */
8457 /*-----------------------------------------------------------------*/
8458 static void AccRsh (int shCount, int andmask)
8459 {
8460         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8461         switch(shCount){
8462                 case 0 :
8463                         return; break;
8464                 case 1 :
8465                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8466                         break;
8467                 case 2 :
8468                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8469                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8470                         break;
8471                 case 3 :
8472                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8473                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8474                         break;
8475                 case 4 :
8476                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8477                         break;
8478                 case 5 :
8479                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8480                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8481                         break;
8482                 case 6 :
8483                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8484                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8485                         break;
8486                 case 7 :
8487                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8488                         break;
8489         }
8490         
8491         if(andmask)
8492                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8493         else
8494                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8495 }
8496
8497 #if 0
8498 /*-----------------------------------------------------------------*/
8499 /* AccSRsh - signed right shift accumulator by known count                 */
8500 /*-----------------------------------------------------------------*/
8501 static void AccSRsh (int shCount)
8502 {
8503     symbol *tlbl ;
8504     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8505     if(shCount != 0){
8506         if(shCount == 1){
8507             pic16_emitcode("mov","c,acc.7");
8508             pic16_emitcode("rrc","a");
8509         } else if(shCount == 2){
8510             pic16_emitcode("mov","c,acc.7");
8511             pic16_emitcode("rrc","a");
8512             pic16_emitcode("mov","c,acc.7");
8513             pic16_emitcode("rrc","a");
8514         } else {
8515             tlbl = newiTempLabel(NULL);
8516             /* rotate right accumulator */
8517             AccRol(8 - shCount);
8518             /* and kill the higher order bits */
8519             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8520             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8521             pic16_emitcode("orl","a,#0x%02x",
8522                      (unsigned char)~SRMask[shCount]);
8523             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8524         }
8525     }
8526 }
8527 #endif
8528
8529 /*-----------------------------------------------------------------*/
8530 /* shiftR1Left2Result - shift right one byte from left to result   */
8531 /*-----------------------------------------------------------------*/
8532 static void shiftR1Left2ResultSigned (operand *left, int offl,
8533                                 operand *result, int offr,
8534                                 int shCount)
8535 {
8536   int same;
8537
8538   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8539
8540   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8541
8542   switch(shCount) {
8543   case 1:
8544     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8545     if(same) 
8546       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8547     else {
8548       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8549       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8550     }
8551
8552     break;
8553   case 2:
8554
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     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8563     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8564
8565     break;
8566
8567   case 3:
8568     if(same)
8569       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8570     else {
8571       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8572       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8573     }
8574
8575     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8576     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8577     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8578
8579     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8580     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8581
8582     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8583     break;
8584
8585   case 4:
8586     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8587     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8588     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8589     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8590     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8591     break;
8592   case 5:
8593     if(same) {
8594       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8595     } else {
8596       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8597       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8598     }
8599     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8600     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8601     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8602     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8603     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8604     break;
8605
8606   case 6:
8607     if(same) {
8608       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8609       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8610       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8611       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8612       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8613       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8614     } else {
8615       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8616       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8617       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8618       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8619       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8620     }
8621     break;
8622
8623   case 7:
8624     if(same) {
8625       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8626       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8627       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8628       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8629     } else {
8630       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8631       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8632       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8633     }
8634
8635   default:
8636     break;
8637   }
8638 }
8639
8640 /*-----------------------------------------------------------------*/
8641 /* shiftR1Left2Result - shift right one byte from left to result   */
8642 /*-----------------------------------------------------------------*/
8643 static void shiftR1Left2Result (operand *left, int offl,
8644                                 operand *result, int offr,
8645                                 int shCount, int sign)
8646 {
8647   int same;
8648
8649   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8650
8651   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8652
8653   /* Copy the msb into the carry if signed. */
8654   if(sign) {
8655     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8656     return;
8657   }
8658
8659
8660
8661   switch(shCount) {
8662   case 1:
8663     emitCLRC;
8664     if(same) 
8665       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8666     else {
8667       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8668       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8669     }
8670     break;
8671   case 2:
8672     emitCLRC;
8673     if(same) {
8674       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8675     } else {
8676       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8677       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8678     }
8679     emitCLRC;
8680     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8681
8682     break;
8683   case 3:
8684     if(same)
8685       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8686     else {
8687       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8688       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8689     }
8690
8691     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8692     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8693     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8694     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8695     break;
8696       
8697   case 4:
8698     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8699     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8700     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8701     break;
8702
8703   case 5:
8704     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8705     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8706     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8707     //emitCLRC;
8708     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8709
8710     break;
8711   case 6:
8712
8713     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8714     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8715     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8716     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8717     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8718     break;
8719
8720   case 7:
8721
8722     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8723     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8724     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8725
8726     break;
8727
8728   default:
8729     break;
8730   }
8731 }
8732
8733 /*-----------------------------------------------------------------*/
8734 /* shiftL1Left2Result - shift left one byte from left to result    */
8735 /*-----------------------------------------------------------------*/
8736 static void shiftL1Left2Result (operand *left, int offl,
8737                                 operand *result, int offr, int shCount)
8738 {
8739   int same;
8740
8741   //    char *l;
8742   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8743
8744   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8745   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8746     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8747     //    MOVA(l);
8748     /* shift left accumulator */
8749     //AccLsh(shCount); // don't comment out just yet...
8750   //    pic16_aopPut(AOP(result),"a",offr);
8751
8752   switch(shCount) {
8753   case 1:
8754     /* Shift left 1 bit position */
8755     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8756     if(same) {
8757       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8758     } else {
8759       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8760       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8761     }
8762     break;
8763   case 2:
8764     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8765     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8766     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8767     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8768     break;
8769   case 3:
8770     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8771     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8772     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8773     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8774     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8775     break;
8776   case 4:
8777     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8778     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8779     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8780     break;
8781   case 5:
8782     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8783     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8784     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8785     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8786     break;
8787   case 6:
8788     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8789     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8790     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8791     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8792     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8793     break;
8794   case 7:
8795     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8796     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8797     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8798     break;
8799
8800   default:
8801     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8802   }
8803
8804 }
8805
8806 /*-----------------------------------------------------------------*/
8807 /* movLeft2Result - move byte from left to result                  */
8808 /*-----------------------------------------------------------------*/
8809 static void movLeft2Result (operand *left, int offl,
8810                             operand *result, int offr)
8811 {
8812   char *l;
8813   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8814   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8815     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8816
8817     if (*l == '@' && (IS_AOP_PREG(result))) {
8818       pic16_emitcode("mov","a,%s",l);
8819       pic16_aopPut(AOP(result),"a",offr);
8820     } else {
8821       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8822       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8823     }
8824   }
8825 }
8826
8827 /*-----------------------------------------------------------------*/
8828 /* shiftL2Left2Result - shift left two bytes from left to result   */
8829 /*-----------------------------------------------------------------*/
8830 static void shiftL2Left2Result (operand *left, int offl,
8831                                 operand *result, int offr, int shCount)
8832 {
8833   int same = pic16_sameRegs(AOP(result), AOP(left));
8834   int i;
8835
8836   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8837
8838   if (same && (offl != offr)) { // shift bytes
8839     if (offr > offl) {
8840        for(i=1;i>-1;i--) {
8841          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8842          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8843        }
8844     } else { // just treat as different later on
8845                 same = 0;
8846     }
8847   }
8848
8849   if(same) {
8850     switch(shCount) {
8851     case 0:
8852       break;
8853     case 1:
8854     case 2:
8855     case 3:
8856
8857       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8858       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8859       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8860
8861       while(--shCount) {
8862                 emitCLRC;
8863                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8864                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8865       }
8866
8867       break;
8868     case 4:
8869     case 5:
8870       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8871       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8872       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8873       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8874       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8875       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8876       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8877       if(shCount >=5) {
8878                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8879                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8880       }
8881       break;
8882     case 6:
8883       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8884       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8885       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8886       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8887       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8888       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8889       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8890       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8891       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8892       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8893       break;
8894     case 7:
8895       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8896       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8897       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8898       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8899       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8900     }
8901
8902   } else {
8903     switch(shCount) {
8904     case 0:
8905       break;
8906     case 1:
8907     case 2:
8908     case 3:
8909       /* note, use a mov/add for the shift since the mov has a
8910          chance of getting optimized out */
8911       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8912       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8913       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8914       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8915       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8916
8917       while(--shCount) {
8918                 emitCLRC;
8919                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8920                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8921       }
8922       break;
8923
8924     case 4:
8925     case 5:
8926       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8927       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8928       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8929       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8930       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8931       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8932       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8933       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8934
8935
8936       if(shCount == 5) {
8937                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8938                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8939       }
8940       break;
8941     case 6:
8942       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8943       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8944       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8945       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8946
8947       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8948       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8949       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8950       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8951       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8952       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8953       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8954       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8955       break;
8956     case 7:
8957       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8958       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8959       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8960       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8961       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8962     }
8963   }
8964
8965 }
8966 /*-----------------------------------------------------------------*/
8967 /* shiftR2Left2Result - shift right two bytes from left to result  */
8968 /*-----------------------------------------------------------------*/
8969 static void shiftR2Left2Result (operand *left, int offl,
8970                                 operand *result, int offr,
8971                                 int shCount, int sign)
8972 {
8973   int same = pic16_sameRegs(AOP(result), AOP(left));
8974   int i;
8975   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8976
8977   if (same && (offl != offr)) { // shift right bytes
8978     if (offr < offl) {
8979        for(i=0;i<2;i++) {
8980          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8981          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8982        }
8983     } else { // just treat as different later on
8984                 same = 0;
8985     }
8986   }
8987
8988   switch(shCount) {
8989   case 0:
8990     break;
8991   case 1:
8992   case 2:
8993   case 3:
8994     if(sign)
8995       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8996     else
8997       emitCLRC;
8998
8999     if(same) {
9000       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9001       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9002     } else {
9003       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9004       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9005       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9006       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9007     }
9008
9009     while(--shCount) {
9010       if(sign)
9011                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9012       else
9013                 emitCLRC;
9014       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9015       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9016     }
9017     break;
9018   case 4:
9019   case 5:
9020     if(same) {
9021
9022       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9023       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9024       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9025
9026       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9027       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9028       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9029       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9030     } else {
9031       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9032       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9033       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9034
9035       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9036       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9037       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9038       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9039       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9040     }
9041
9042     if(shCount >=5) {
9043       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9044       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9045     }
9046
9047     if(sign) {
9048       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9049       pic16_emitpcode(POC_BTFSC, 
9050                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9051       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9052     }
9053
9054     break;
9055
9056   case 6:
9057     if(same) {
9058
9059       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9060       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9061
9062       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9063       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9064       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9065       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9066       if(sign) {
9067         pic16_emitpcode(POC_BTFSC, 
9068                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9069         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9070       }
9071       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9072       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9073       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9074       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9075     } else {
9076       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9077       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9078       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9079       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9080       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9081       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9082       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9083       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9084       if(sign) {
9085         pic16_emitpcode(POC_BTFSC, 
9086                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9087         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9088       }
9089       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9090       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9091
9092         
9093     }
9094
9095     break;
9096   case 7:
9097     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9098     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9099     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9100     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9101     if(sign) {
9102       emitSKPNC;
9103       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9104     } else 
9105       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9106   }
9107 }
9108
9109
9110 /*-----------------------------------------------------------------*/
9111 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9112 /*-----------------------------------------------------------------*/
9113 static void shiftLLeftOrResult (operand *left, int offl,
9114                                 operand *result, int offr, int shCount)
9115 {
9116     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9117
9118     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9119     /* shift left accumulator */
9120     AccLsh(shCount);
9121     /* or with result */
9122     /* back to result */
9123     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9124 }
9125
9126 /*-----------------------------------------------------------------*/
9127 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9128 /*-----------------------------------------------------------------*/
9129 static void shiftRLeftOrResult (operand *left, int offl,
9130                                 operand *result, int offr, int shCount)
9131 {
9132     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9133     
9134     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9135     /* shift right accumulator */
9136     AccRsh(shCount, 1);
9137     /* or with result */
9138     /* back to result */
9139     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9140 }
9141
9142 /*-----------------------------------------------------------------*/
9143 /* genlshOne - left shift a one byte quantity by known count       */
9144 /*-----------------------------------------------------------------*/
9145 static void genlshOne (operand *result, operand *left, int shCount)
9146 {       
9147     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9148     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9149 }
9150
9151 /*-----------------------------------------------------------------*/
9152 /* genlshTwo - left shift two bytes by known amount != 0           */
9153 /*-----------------------------------------------------------------*/
9154 static void genlshTwo (operand *result,operand *left, int shCount)
9155 {
9156     int size;
9157     
9158     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9159     size = pic16_getDataSize(result);
9160
9161     /* if shCount >= 8 */
9162     if (shCount >= 8) {
9163         shCount -= 8 ;
9164
9165         if (size > 1){
9166             if (shCount)
9167                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9168             else 
9169                 movLeft2Result(left, LSB, result, MSB16);
9170         }
9171         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9172     }
9173
9174     /*  1 <= shCount <= 7 */
9175     else {  
9176         if(size == 1)
9177             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9178         else 
9179             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9180     }
9181 }
9182
9183 /*-----------------------------------------------------------------*/
9184 /* shiftLLong - shift left one long from left to result            */
9185 /* offr = LSB or MSB16                                             */
9186 /*-----------------------------------------------------------------*/
9187 static void shiftLLong (operand *left, operand *result, int offr )
9188 {
9189     int size = AOP_SIZE(result);
9190     int same = pic16_sameRegs(AOP(left),AOP(result));
9191         int i;
9192
9193     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9194
9195         if (same && (offr == MSB16)) { //shift one byte
9196                 for(i=size-1;i>=MSB16;i--) {
9197                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9198                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9199                 }
9200         } else {
9201                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9202         }
9203         
9204     if (size > LSB+offr ){
9205                 if (same) {
9206                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9207                 } else {
9208                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9209                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9210                 }
9211          }
9212
9213     if(size > MSB16+offr){
9214                 if (same) {
9215                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9216                 } else {
9217                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9218                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9219                 }
9220     }
9221
9222     if(size > MSB24+offr){
9223                 if (same) {
9224                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9225                 } else {
9226                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9227                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9228                 }
9229     }
9230
9231     if(size > MSB32+offr){
9232                 if (same) {
9233                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9234                 } else {
9235                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9236                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9237                 }
9238     }
9239     if(offr != LSB)
9240                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9241
9242 }
9243
9244 /*-----------------------------------------------------------------*/
9245 /* genlshFour - shift four byte by a known amount != 0             */
9246 /*-----------------------------------------------------------------*/
9247 static void genlshFour (operand *result, operand *left, int shCount)
9248 {
9249     int size;
9250
9251     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9252     size = AOP_SIZE(result);
9253
9254     /* if shifting more that 3 bytes */
9255     if (shCount >= 24 ) {
9256         shCount -= 24;
9257         if (shCount)
9258             /* lowest order of left goes to the highest
9259             order of the destination */
9260             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9261         else
9262             movLeft2Result(left, LSB, result, MSB32);
9263
9264                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9265                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9266                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9267
9268         return;
9269     }
9270
9271     /* more than two bytes */
9272     else if ( shCount >= 16 ) {
9273         /* lower order two bytes goes to higher order two bytes */
9274         shCount -= 16;
9275         /* if some more remaining */
9276         if (shCount)
9277             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9278         else {
9279             movLeft2Result(left, MSB16, result, MSB32);
9280             movLeft2Result(left, LSB, result, MSB24);
9281         }
9282                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9283                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9284         return;
9285     }    
9286
9287     /* if more than 1 byte */
9288     else if ( shCount >= 8 ) {
9289         /* lower order three bytes goes to higher order  three bytes */
9290         shCount -= 8;
9291         if(size == 2){
9292             if(shCount)
9293                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9294             else
9295                 movLeft2Result(left, LSB, result, MSB16);
9296         }
9297         else{   /* size = 4 */
9298             if(shCount == 0){
9299                 movLeft2Result(left, MSB24, result, MSB32);
9300                 movLeft2Result(left, MSB16, result, MSB24);
9301                 movLeft2Result(left, LSB, result, MSB16);
9302                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9303             }
9304             else if(shCount == 1)
9305                 shiftLLong(left, result, MSB16);
9306             else{
9307                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9308                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9309                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9310                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9311             }
9312         }
9313     }
9314
9315     /* 1 <= shCount <= 7 */
9316     else if(shCount <= 3)
9317     { 
9318         shiftLLong(left, result, LSB);
9319         while(--shCount >= 1)
9320             shiftLLong(result, result, LSB);
9321     }
9322     /* 3 <= shCount <= 7, optimize */
9323     else{
9324         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9325         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9326         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9327     }
9328 }
9329
9330 /*-----------------------------------------------------------------*/
9331 /* genLeftShiftLiteral - left shifting by known count              */
9332 /*-----------------------------------------------------------------*/
9333 void pic16_genLeftShiftLiteral (operand *left,
9334                                  operand *right,
9335                                  operand *result,
9336                                  iCode *ic)
9337 {    
9338     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
9339     int size;
9340
9341     FENTRY;
9342     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9343     pic16_freeAsmop(right,NULL,ic,TRUE);
9344
9345     pic16_aopOp(left,ic,FALSE);
9346     pic16_aopOp(result,ic,FALSE);
9347
9348     size = getSize(operandType(result));
9349
9350 #if VIEW_SIZE
9351     pic16_emitcode("; shift left ","result %d, left %d",size,
9352              AOP_SIZE(left));
9353 #endif
9354
9355     /* I suppose that the left size >= result size */
9356     if(shCount == 0){
9357         while(size--){
9358             movLeft2Result(left, size, result, size);
9359         }
9360     }
9361
9362     else if(shCount >= (size * 8))
9363         while(size--)
9364             pic16_aopPut(AOP(result),zero,size);
9365     else{
9366         switch (size) {
9367             case 1:
9368                 genlshOne (result,left,shCount);
9369                 break;
9370
9371             case 2:
9372             case 3:
9373                 genlshTwo (result,left,shCount);
9374                 break;
9375
9376             case 4:
9377                 genlshFour (result,left,shCount);
9378                 break;
9379         }
9380     }
9381     pic16_freeAsmop(left,NULL,ic,TRUE);
9382     pic16_freeAsmop(result,NULL,ic,TRUE);
9383 }
9384
9385 /*-----------------------------------------------------------------*
9386  * genMultiAsm - repeat assembly instruction for size of register.
9387  * if endian == 1, then the high byte (i.e base address + size of 
9388  * register) is used first else the low byte is used first;
9389  *-----------------------------------------------------------------*/
9390 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9391 {
9392
9393   int offset = 0;
9394
9395   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9396
9397   if(!reg)
9398     return;
9399
9400   if(!endian) {
9401     endian = 1;
9402   } else {
9403     endian = -1;
9404     offset = size-1;
9405   }
9406
9407   while(size--) {
9408     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9409     offset += endian;
9410   }
9411
9412 }
9413 /*-----------------------------------------------------------------*/
9414 /* genLeftShift - generates code for left shifting                 */
9415 /*-----------------------------------------------------------------*/
9416 static void genLeftShift (iCode *ic)
9417 {
9418   operand *left,*right, *result;
9419   int size, offset;
9420 //  char *l;
9421   symbol *tlbl , *tlbl1;
9422   pCodeOp *pctemp;
9423
9424   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9425
9426   right = IC_RIGHT(ic);
9427   left  = IC_LEFT(ic);
9428   result = IC_RESULT(ic);
9429
9430   pic16_aopOp(right,ic,FALSE);
9431
9432   /* if the shift count is known then do it 
9433      as efficiently as possible */
9434   if (AOP_TYPE(right) == AOP_LIT) {
9435     pic16_genLeftShiftLiteral (left,right,result,ic);
9436     return ;
9437   }
9438
9439   /* shift count is unknown then we have to form
9440    * a loop. Get the loop count in WREG : Note: we take
9441    * only the lower order byte since shifting
9442    * more than 32 bits make no sense anyway, ( the
9443    * largest size of an object can be only 32 bits ) */
9444   
9445   pic16_aopOp(left,ic,FALSE);
9446   pic16_aopOp(result,ic,FALSE);
9447
9448   /* now move the left to the result if they are not the
9449    * same, and if size > 1,
9450    * and if right is not same to result (!!!) -- VR */
9451   if (!pic16_sameRegs(AOP(left),AOP(result))
9452       && (AOP_SIZE(result) > 1)) {
9453
9454     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9455
9456     size = AOP_SIZE(result);
9457     offset=0;
9458     while (size--) {
9459
9460 #if 0
9461       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9462       if (*l == '@' && (IS_AOP_PREG(result))) {
9463
9464           pic16_emitcode("mov","a,%s",l);
9465           pic16_aopPut(AOP(result),"a",offset);
9466       } else
9467 #endif
9468       {
9469         /* we don't know if left is a literal or a register, take care -- VR */
9470         mov2f(AOP(result), AOP(left), offset);
9471       }
9472       offset++;
9473     }
9474   }
9475
9476   size = AOP_SIZE(result);
9477
9478   /* if it is only one byte then */
9479   if (size == 1) {
9480     if(optimized_for_speed) {
9481       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9482       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9483       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9484       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9485       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9486       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9487       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9488       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9489       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9490       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9491       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9492       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9493     } else {
9494
9495       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9496
9497       tlbl = newiTempLabel(NULL);
9498
9499 #if 1
9500       /* this is already done, why change it? */
9501       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9502                 mov2f(AOP(result), AOP(left), 0);
9503       }
9504 #endif
9505
9506       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9507       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9508       pic16_emitpLabel(tlbl->key);
9509       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9510       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9511       emitSKPC;
9512       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9513     }
9514     goto release ;
9515   }
9516     
9517   if (pic16_sameRegs(AOP(left),AOP(result))) {
9518
9519     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9520     
9521     tlbl = newiTempLabel(NULL);
9522     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9523     genMultiAsm(POC_RRCF, result, size,1);
9524     pic16_emitpLabel(tlbl->key);
9525     genMultiAsm(POC_RLCF, result, size,0);
9526     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9527     emitSKPC;
9528     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9529     goto release;
9530   }
9531
9532   //tlbl = newiTempLabel(NULL);
9533   //offset = 0 ;   
9534   //tlbl1 = newiTempLabel(NULL);
9535
9536   //reAdjustPreg(AOP(result));    
9537     
9538   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9539   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9540   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9541   //MOVA(l);
9542   //pic16_emitcode("add","a,acc");         
9543   //pic16_aopPut(AOP(result),"a",offset++);
9544   //while (--size) {
9545   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9546   //  MOVA(l);
9547   //  pic16_emitcode("rlc","a");         
9548   //  pic16_aopPut(AOP(result),"a",offset++);
9549   //}
9550   //reAdjustPreg(AOP(result));
9551
9552   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9553   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9554
9555
9556   tlbl = newiTempLabel(NULL);
9557   tlbl1= newiTempLabel(NULL);
9558
9559   size = AOP_SIZE(result);
9560   offset = 1;
9561
9562   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9563
9564   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9565
9566   /* offset should be 0, 1 or 3 */
9567   
9568   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9569   emitSKPNZ;
9570   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9571
9572   pic16_emitpcode(POC_MOVWF, pctemp);
9573
9574
9575   pic16_emitpLabel(tlbl->key);
9576
9577   emitCLRC;
9578   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9579   while(--size)
9580     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9581
9582   pic16_emitpcode(POC_DECFSZ,  pctemp);
9583   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9584   pic16_emitpLabel(tlbl1->key);
9585
9586   pic16_popReleaseTempReg(pctemp,1);
9587
9588
9589  release:
9590   pic16_freeAsmop (right,NULL,ic,TRUE);
9591   pic16_freeAsmop(left,NULL,ic,TRUE);
9592   pic16_freeAsmop(result,NULL,ic,TRUE);
9593 }
9594
9595
9596
9597 #if 0
9598 #error old code (left here for reference)
9599 /*-----------------------------------------------------------------*/
9600 /* genLeftShift - generates code for left shifting                 */
9601 /*-----------------------------------------------------------------*/
9602 static void genLeftShift (iCode *ic)
9603 {
9604   operand *left,*right, *result;
9605   int size, offset;
9606   char *l;
9607   symbol *tlbl , *tlbl1;
9608   pCodeOp *pctemp;
9609
9610   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9611
9612   right = IC_RIGHT(ic);
9613   left  = IC_LEFT(ic);
9614   result = IC_RESULT(ic);
9615
9616   pic16_aopOp(right,ic,FALSE);
9617
9618   /* if the shift count is known then do it 
9619      as efficiently as possible */
9620   if (AOP_TYPE(right) == AOP_LIT) {
9621     pic16_genLeftShiftLiteral (left,right,result,ic);
9622     return ;
9623   }
9624
9625   /* shift count is unknown then we have to form 
9626      a loop get the loop count in B : Note: we take
9627      only the lower order byte since shifting
9628      more that 32 bits make no sense anyway, ( the
9629      largest size of an object can be only 32 bits ) */  
9630
9631     
9632   pic16_aopOp(left,ic,FALSE);
9633   pic16_aopOp(result,ic,FALSE);
9634
9635   /* now move the left to the result if they are not the
9636      same */
9637   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9638       AOP_SIZE(result) > 1) {
9639
9640     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9641
9642     size = AOP_SIZE(result);
9643     offset=0;
9644     while (size--) {
9645       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9646       if (*l == '@' && (IS_AOP_PREG(result))) {
9647
9648         pic16_emitcode("mov","a,%s",l);
9649         pic16_aopPut(AOP(result),"a",offset);
9650       } else {
9651
9652         /* we don't know if left is a literal or a register, take care -- VR */
9653         mov2f(AOP(result), AOP(left), offset);
9654       }
9655       offset++;
9656     }
9657   }
9658
9659   size = AOP_SIZE(result);
9660
9661   /* if it is only one byte then */
9662   if (size == 1) {
9663     if(optimized_for_speed) {
9664       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9665       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9666       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9667       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9668       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9669       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9670       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9671       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9672       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9673       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9674       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9675       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9676     } else {
9677
9678       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9679
9680       tlbl = newiTempLabel(NULL);
9681       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9682                 mov2f(AOP(result), AOP(left), 0);
9683                 
9684 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9685 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9686       }
9687
9688       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9689       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9690       pic16_emitpLabel(tlbl->key);
9691       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9692       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9693       emitSKPC;
9694       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9695     }
9696     goto release ;
9697   }
9698     
9699   if (pic16_sameRegs(AOP(left),AOP(result))) {
9700
9701     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9702     
9703     tlbl = newiTempLabel(NULL);
9704     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9705     genMultiAsm(POC_RRCF, result, size,1);
9706     pic16_emitpLabel(tlbl->key);
9707     genMultiAsm(POC_RLCF, result, size,0);
9708     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9709     emitSKPC;
9710     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9711     goto release;
9712   }
9713
9714   //tlbl = newiTempLabel(NULL);
9715   //offset = 0 ;   
9716   //tlbl1 = newiTempLabel(NULL);
9717
9718   //reAdjustPreg(AOP(result));    
9719     
9720   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9721   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9722   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9723   //MOVA(l);
9724   //pic16_emitcode("add","a,acc");         
9725   //pic16_aopPut(AOP(result),"a",offset++);
9726   //while (--size) {
9727   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9728   //  MOVA(l);
9729   //  pic16_emitcode("rlc","a");         
9730   //  pic16_aopPut(AOP(result),"a",offset++);
9731   //}
9732   //reAdjustPreg(AOP(result));
9733
9734   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9735   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9736
9737
9738   tlbl = newiTempLabel(NULL);
9739   tlbl1= newiTempLabel(NULL);
9740
9741   size = AOP_SIZE(result);
9742   offset = 1;
9743
9744   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9745
9746   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9747
9748   /* offset should be 0, 1 or 3 */
9749   
9750   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9751   emitSKPNZ;
9752   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9753
9754   pic16_emitpcode(POC_MOVWF, pctemp);
9755
9756
9757   pic16_emitpLabel(tlbl->key);
9758
9759   emitCLRC;
9760   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9761   while(--size)
9762     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9763
9764   pic16_emitpcode(POC_DECFSZ,  pctemp);
9765   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9766   pic16_emitpLabel(tlbl1->key);
9767
9768   pic16_popReleaseTempReg(pctemp,1);
9769
9770
9771  release:
9772   pic16_freeAsmop (right,NULL,ic,TRUE);
9773   pic16_freeAsmop(left,NULL,ic,TRUE);
9774   pic16_freeAsmop(result,NULL,ic,TRUE);
9775 }
9776 #endif
9777
9778 /*-----------------------------------------------------------------*/
9779 /* genrshOne - right shift a one byte quantity by known count      */
9780 /*-----------------------------------------------------------------*/
9781 static void genrshOne (operand *result, operand *left,
9782                        int shCount, int sign)
9783 {
9784     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9785     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9786 }
9787
9788 /*-----------------------------------------------------------------*/
9789 /* genrshTwo - right shift two bytes by known amount != 0          */
9790 /*-----------------------------------------------------------------*/
9791 static void genrshTwo (operand *result,operand *left,
9792                        int shCount, int sign)
9793 {
9794   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9795   /* if shCount >= 8 */
9796   if (shCount >= 8) {
9797     shCount -= 8 ;
9798     if (shCount)
9799       shiftR1Left2Result(left, MSB16, result, LSB,
9800                          shCount, sign);
9801     else
9802       movLeft2Result(left, MSB16, result, LSB);
9803
9804     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9805
9806     if(sign) {
9807       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9808       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
9809     }
9810   }
9811
9812   /*  1 <= shCount <= 7 */
9813   else
9814     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9815 }
9816
9817 /*-----------------------------------------------------------------*/
9818 /* shiftRLong - shift right one long from left to result           */
9819 /* offl = LSB or MSB16                                             */
9820 /*-----------------------------------------------------------------*/
9821 static void shiftRLong (operand *left, int offl,
9822                         operand *result, int sign)
9823 {
9824     int size = AOP_SIZE(result);
9825     int same = pic16_sameRegs(AOP(left),AOP(result));
9826     int i;
9827     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9828
9829         if (same && (offl == MSB16)) { //shift one byte right
9830                 for(i=MSB16;i<size;i++) {
9831                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9832                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9833                 }
9834         }
9835
9836     if(sign)
9837                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9838         else
9839                 emitCLRC;
9840
9841         if (same) {
9842                 if (offl == LSB)
9843                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9844         } else {
9845         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9846         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9847         }
9848
9849     if(offl == MSB16) {
9850         /* add sign of "a" */
9851         pic16_addSign(result, MSB32, sign);
9852         }
9853
9854         if (same) {
9855         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9856         } else {
9857         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9858         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9859         }
9860         
9861         if (same) {
9862         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9863         } else {
9864         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9865         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9866         }
9867
9868         if (same) {
9869         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9870         } else {
9871         if(offl == LSB){
9872                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9873                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9874         }
9875         }
9876 }
9877
9878 /*-----------------------------------------------------------------*/
9879 /* genrshFour - shift four byte by a known amount != 0             */
9880 /*-----------------------------------------------------------------*/
9881 static void genrshFour (operand *result, operand *left,
9882                         int shCount, int sign)
9883 {
9884   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9885   /* if shifting more that 3 bytes */
9886   if(shCount >= 24 ) {
9887     shCount -= 24;
9888     if(shCount)
9889       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9890     else
9891       movLeft2Result(left, MSB32, result, LSB);
9892
9893     pic16_addSign(result, MSB16, sign);
9894   }
9895   else if(shCount >= 16){
9896     shCount -= 16;
9897     if(shCount)
9898       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9899     else{
9900       movLeft2Result(left, MSB24, result, LSB);
9901       movLeft2Result(left, MSB32, result, MSB16);
9902     }
9903     pic16_addSign(result, MSB24, sign);
9904   }
9905   else if(shCount >= 8){
9906     shCount -= 8;
9907     if(shCount == 1)
9908       shiftRLong(left, MSB16, result, sign);
9909     else if(shCount == 0){
9910       movLeft2Result(left, MSB16, result, LSB);
9911       movLeft2Result(left, MSB24, result, MSB16);
9912       movLeft2Result(left, MSB32, result, MSB24);
9913       pic16_addSign(result, MSB32, sign);
9914     }
9915     else{ //shcount >= 2
9916       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9917       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9918       /* the last shift is signed */
9919       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9920       pic16_addSign(result, MSB32, sign);
9921     }
9922   }
9923   else{   /* 1 <= shCount <= 7 */
9924     if(shCount <= 2){
9925       shiftRLong(left, LSB, result, sign);
9926       if(shCount == 2)
9927         shiftRLong(result, LSB, result, sign);
9928     }
9929     else{
9930       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9931       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9932       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9933     }
9934   }
9935 }
9936
9937 /*-----------------------------------------------------------------*/
9938 /* genRightShiftLiteral - right shifting by known count            */
9939 /*-----------------------------------------------------------------*/
9940 static void genRightShiftLiteral (operand *left,
9941                                   operand *right,
9942                                   operand *result,
9943                                   iCode *ic,
9944                                   int sign)
9945 {    
9946   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
9947   int lsize,res_size;
9948
9949   pic16_freeAsmop(right,NULL,ic,TRUE);
9950
9951   pic16_aopOp(left,ic,FALSE);
9952   pic16_aopOp(result,ic,FALSE);
9953
9954   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9955
9956 #if VIEW_SIZE
9957   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9958                  AOP_SIZE(left));
9959 #endif
9960
9961   lsize = pic16_getDataSize(left);
9962   res_size = pic16_getDataSize(result);
9963   /* test the LEFT size !!! */
9964
9965   /* I suppose that the left size >= result size */
9966   if(shCount == 0){
9967     while(res_size--)
9968       movLeft2Result(left, lsize, result, res_size);
9969   }
9970
9971   else if(shCount >= (lsize * 8)){
9972
9973     if(res_size == 1) {
9974       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9975       if(sign) {
9976         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9977         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
9978       }
9979     } else {
9980
9981       if(sign) {
9982         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
9983         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9984         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9985         while(res_size--)
9986           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
9987
9988       } else {
9989
9990         while(res_size--)
9991           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
9992       }
9993     }
9994   } else {
9995
9996     switch (res_size) {
9997     case 1:
9998       genrshOne (result,left,shCount,sign);
9999       break;
10000
10001     case 2:
10002       genrshTwo (result,left,shCount,sign);
10003       break;
10004
10005     case 4:
10006       genrshFour (result,left,shCount,sign);
10007       break;
10008     default :
10009       break;
10010     }
10011
10012   }
10013
10014   pic16_freeAsmop(left,NULL,ic,TRUE);
10015   pic16_freeAsmop(result,NULL,ic,TRUE);
10016 }
10017
10018 /*-----------------------------------------------------------------*/
10019 /* genSignedRightShift - right shift of signed number              */
10020 /*-----------------------------------------------------------------*/
10021 static void genSignedRightShift (iCode *ic)
10022 {
10023   operand *right, *left, *result;
10024   int size, offset;
10025   //  char *l;
10026   symbol *tlbl, *tlbl1 ;
10027   pCodeOp *pctemp;
10028
10029   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10030
10031   /* we do it the hard way put the shift count in b
10032      and loop thru preserving the sign */
10033   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10034
10035   right = IC_RIGHT(ic);
10036   left  = IC_LEFT(ic);
10037   result = IC_RESULT(ic);
10038
10039   pic16_aopOp(right,ic,FALSE);  
10040   pic16_aopOp(left,ic,FALSE);
10041   pic16_aopOp(result,ic,FALSE);
10042
10043
10044   if ( AOP_TYPE(right) == AOP_LIT) {
10045     genRightShiftLiteral (left,right,result,ic,1);
10046     return ;
10047   }
10048   /* shift count is unknown then we have to form 
10049      a loop get the loop count in B : Note: we take
10050      only the lower order byte since shifting
10051      more that 32 bits make no sense anyway, ( the
10052      largest size of an object can be only 32 bits ) */  
10053
10054   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10055   //pic16_emitcode("inc","b");
10056   //pic16_freeAsmop (right,NULL,ic,TRUE);
10057   //pic16_aopOp(left,ic,FALSE);
10058   //pic16_aopOp(result,ic,FALSE);
10059
10060   /* now move the left to the result if they are not the
10061      same */
10062   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10063       AOP_SIZE(result) > 1) {
10064
10065     size = AOP_SIZE(result);
10066     offset=0;
10067     while (size--) { 
10068       /*
10069         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10070         if (*l == '@' && IS_AOP_PREG(result)) {
10071
10072         pic16_emitcode("mov","a,%s",l);
10073         pic16_aopPut(AOP(result),"a",offset);
10074         } else
10075         pic16_aopPut(AOP(result),l,offset);
10076       */
10077       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10078       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10079
10080       offset++;
10081     }
10082   }
10083
10084   /* mov the highest order bit to OVR */    
10085   tlbl = newiTempLabel(NULL);
10086   tlbl1= newiTempLabel(NULL);
10087
10088   size = AOP_SIZE(result);
10089   offset = size - 1;
10090
10091   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10092
10093   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10094
10095   /* offset should be 0, 1 or 3 */
10096   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10097   emitSKPNZ;
10098   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10099
10100   pic16_emitpcode(POC_MOVWF, pctemp);
10101
10102
10103   pic16_emitpLabel(tlbl->key);
10104
10105   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10106   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10107
10108   while(--size) {
10109     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10110   }
10111
10112   pic16_emitpcode(POC_DECFSZ,  pctemp);
10113   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10114   pic16_emitpLabel(tlbl1->key);
10115
10116   pic16_popReleaseTempReg(pctemp,1);
10117 #if 0
10118   size = AOP_SIZE(result);
10119   offset = size - 1;
10120   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10121   pic16_emitcode("rlc","a");
10122   pic16_emitcode("mov","ov,c");
10123   /* if it is only one byte then */
10124   if (size == 1) {
10125     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10126     MOVA(l);
10127     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10128     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10129     pic16_emitcode("mov","c,ov");
10130     pic16_emitcode("rrc","a");
10131     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10132     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10133     pic16_aopPut(AOP(result),"a",0);
10134     goto release ;
10135   }
10136
10137   reAdjustPreg(AOP(result));
10138   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10139   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10140   pic16_emitcode("mov","c,ov");
10141   while (size--) {
10142     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10143     MOVA(l);
10144     pic16_emitcode("rrc","a");         
10145     pic16_aopPut(AOP(result),"a",offset--);
10146   }
10147   reAdjustPreg(AOP(result));
10148   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10149   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10150
10151  release:
10152 #endif
10153
10154   pic16_freeAsmop(left,NULL,ic,TRUE);
10155   pic16_freeAsmop(result,NULL,ic,TRUE);
10156   pic16_freeAsmop(right,NULL,ic,TRUE);
10157 }
10158
10159 /*-----------------------------------------------------------------*/
10160 /* genRightShift - generate code for right shifting                */
10161 /*-----------------------------------------------------------------*/
10162 static void genRightShift (iCode *ic)
10163 {
10164     operand *right, *left, *result;
10165     sym_link *letype ;
10166     int size, offset;
10167     char *l;
10168     symbol *tlbl, *tlbl1 ;
10169
10170     /* if signed then we do it the hard way preserve the
10171     sign bit moving it inwards */
10172     letype = getSpec(operandType(IC_LEFT(ic)));
10173     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10174
10175     if (!SPEC_USIGN(letype)) {
10176         genSignedRightShift (ic);
10177         return ;
10178     }
10179
10180     /* signed & unsigned types are treated the same : i.e. the
10181     signed is NOT propagated inwards : quoting from the
10182     ANSI - standard : "for E1 >> E2, is equivalent to division
10183     by 2**E2 if unsigned or if it has a non-negative value,
10184     otherwise the result is implementation defined ", MY definition
10185     is that the sign does not get propagated */
10186
10187     right = IC_RIGHT(ic);
10188     left  = IC_LEFT(ic);
10189     result = IC_RESULT(ic);
10190
10191     pic16_aopOp(right,ic,FALSE);
10192
10193     /* if the shift count is known then do it 
10194     as efficiently as possible */
10195     if (AOP_TYPE(right) == AOP_LIT) {
10196         genRightShiftLiteral (left,right,result,ic, 0);
10197         return ;
10198     }
10199
10200     /* shift count is unknown then we have to form 
10201     a loop get the loop count in B : Note: we take
10202     only the lower order byte since shifting
10203     more that 32 bits make no sense anyway, ( the
10204     largest size of an object can be only 32 bits ) */  
10205
10206     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10207     pic16_emitcode("inc","b");
10208     pic16_aopOp(left,ic,FALSE);
10209     pic16_aopOp(result,ic,FALSE);
10210
10211     /* now move the left to the result if they are not the
10212     same */
10213     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10214         AOP_SIZE(result) > 1) {
10215
10216         size = AOP_SIZE(result);
10217         offset=0;
10218         while (size--) {
10219             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10220             if (*l == '@' && IS_AOP_PREG(result)) {
10221
10222                 pic16_emitcode("mov","a,%s",l);
10223                 pic16_aopPut(AOP(result),"a",offset);
10224             } else
10225                 pic16_aopPut(AOP(result),l,offset);
10226             offset++;
10227         }
10228     }
10229
10230     tlbl = newiTempLabel(NULL);
10231     tlbl1= newiTempLabel(NULL);
10232     size = AOP_SIZE(result);
10233     offset = size - 1;
10234
10235     /* if it is only one byte then */
10236     if (size == 1) {
10237
10238       tlbl = newiTempLabel(NULL);
10239       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10240         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10241         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10242       }
10243
10244       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10245       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10246       pic16_emitpLabel(tlbl->key);
10247       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10248       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10249       emitSKPC;
10250       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10251
10252       goto release ;
10253     }
10254
10255     reAdjustPreg(AOP(result));
10256     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10257     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10258     CLRC;
10259     while (size--) {
10260         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10261         MOVA(l);
10262         pic16_emitcode("rrc","a");         
10263         pic16_aopPut(AOP(result),"a",offset--);
10264     }
10265     reAdjustPreg(AOP(result));
10266
10267     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10268     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10269
10270 release:
10271     pic16_freeAsmop(left,NULL,ic,TRUE);
10272     pic16_freeAsmop (right,NULL,ic,TRUE);
10273     pic16_freeAsmop(result,NULL,ic,TRUE);
10274 }
10275
10276
10277 void pic16_loadFSR0(operand *op)
10278 {
10279         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10280 }
10281
10282 /*-----------------------------------------------------------------*/
10283 /* genUnpackBits - generates code for unpacking bits               */
10284 /*-----------------------------------------------------------------*/
10285 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10286 {    
10287   int shCnt ;
10288   int rlen = 0 ;
10289   sym_link *etype, *letype;
10290   int blen=0, bstr=0;
10291   int lbstr;
10292   int offset = 0 ;
10293
10294     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10295     etype = getSpec(operandType(result));
10296     letype = getSpec(operandType(left));
10297     
10298 //    if(IS_BITFIELD(etype)) {
10299       blen = SPEC_BLEN(etype);
10300       bstr = SPEC_BSTR(etype);
10301 //    }
10302
10303     lbstr = SPEC_BSTR( letype );
10304
10305 #if 1
10306     if((blen == 1) && (bstr < 8)) {
10307       /* it is a single bit, so use the appropriate bit instructions */
10308       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10309
10310       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10311       
10312       if((ptype == POINTER) && (result)) {
10313         /* workaround to reduce the extra lfsr instruction */
10314         pic16_emitpcode(POC_BTFSC,
10315               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10316       } else {
10317         pic16_emitpcode(POC_BTFSC,
10318               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10319       }
10320         
10321       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10322
10323       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10324       return;
10325     }
10326
10327 #endif
10328
10329         /* the following call to pic16_loadFSR0 is temporary until
10330          * optimization to handle single bit assignments is added
10331          * to the function. Until then use the old safe way! -- VR */
10332         pic16_loadFSR0( left );
10333  
10334         /* read the first byte  */
10335         switch (ptype) {
10336                 case POINTER:
10337                 case IPOINTER:
10338                 case PPOINTER:
10339                 case FPOINTER:
10340                 case GPOINTER:
10341                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10342                         break;
10343                 case CPOINTER:
10344                         pic16_emitcode("clr","a");
10345                         pic16_emitcode("movc","a","@a+dptr");
10346                         break;
10347         }
10348         
10349
10350         /* if we have bitdisplacement then it fits   */
10351         /* into this byte completely or if length is */
10352         /* less than a byte                          */
10353         if ((shCnt = SPEC_BSTR(etype)) || 
10354                 (SPEC_BLEN(etype) <= 8))  {
10355
10356                 /* shift right acc */
10357                 AccRsh(shCnt, 0);
10358
10359                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10360                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10361
10362 /* VR -- normally I would use the following, but since we use the hack,
10363  * to avoid the masking from AccRsh, why not mask it right now? */
10364
10365 /*
10366                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10367 */
10368
10369                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10370           return ;
10371         }
10372
10373
10374
10375         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10376         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10377         exit(-1);
10378
10379     /* bit field did not fit in a byte  */
10380     rlen = SPEC_BLEN(etype) - 8;
10381     pic16_aopPut(AOP(result),"a",offset++);
10382
10383     while (1)  {
10384
10385         switch (ptype) {
10386         case POINTER:
10387         case IPOINTER:
10388             pic16_emitcode("inc","%s",rname);
10389             pic16_emitcode("mov","a,@%s",rname);
10390             break;
10391             
10392         case PPOINTER:
10393             pic16_emitcode("inc","%s",rname);
10394             pic16_emitcode("movx","a,@%s",rname);
10395             break;
10396
10397         case FPOINTER:
10398             pic16_emitcode("inc","dptr");
10399             pic16_emitcode("movx","a,@dptr");
10400             break;
10401             
10402         case CPOINTER:
10403             pic16_emitcode("clr","a");
10404             pic16_emitcode("inc","dptr");
10405             pic16_emitcode("movc","a","@a+dptr");
10406             break;
10407             
10408         case GPOINTER:
10409             pic16_emitcode("inc","dptr");
10410             pic16_emitcode("lcall","__gptrget");
10411             break;
10412         }
10413
10414         rlen -= 8;            
10415         /* if we are done */
10416         if ( rlen <= 0 )
10417             break ;
10418         
10419         pic16_aopPut(AOP(result),"a",offset++);
10420                               
10421     }
10422     
10423     if (rlen) {
10424         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10425         pic16_aopPut(AOP(result),"a",offset);          
10426     }
10427     
10428     return ;
10429 }
10430
10431
10432 static void genDataPointerGet(operand *left,
10433                               operand *result,
10434                               iCode *ic)
10435 {
10436   int size, offset = 0, leoffset=0 ;
10437
10438         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10439         pic16_aopOp(result, ic, FALSE);
10440
10441         size = AOP_SIZE(result);
10442 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10443
10444
10445 #if 0
10446         /* The following tests may save a redudant movff instruction when
10447          * accessing unions */
10448          
10449         /* if they are the same */
10450         if (operandsEqu (left, result)) {
10451                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10452                 goto release;
10453         }
10454 #endif
10455
10456 #if 0
10457         /* if they are the same registers */
10458         if (pic16_sameRegs(AOP(left),AOP(result))) {
10459                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10460                 goto release;
10461         }
10462 #endif
10463
10464 #if 1
10465         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10466                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10467                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10468                 goto release;
10469         }
10470 #endif
10471
10472
10473 #if 0
10474         if ( AOP_TYPE(left) == AOP_PCODE) {
10475                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
10476                                 AOP(left)->aopu.pcop->name,
10477                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
10478                                 PCOR(AOP(left)->aopu.pcop)->instance:
10479                                 PCOI(AOP(left)->aopu.pcop)->offset);
10480         }
10481 #endif
10482
10483         if(AOP(left)->aopu.pcop->type == PO_DIR)
10484                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10485
10486         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10487
10488         while (size--) {
10489                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10490                 
10491                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
10492                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
10493                         mov2w(AOP(left), offset); // patch 8
10494                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10495                 } else {
10496                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10497                                 pic16_popGet(AOP(left), offset), //patch 8
10498                                 pic16_popGet(AOP(result), offset)));
10499                 }
10500
10501                 offset++;
10502                 leoffset++;
10503         }
10504
10505 release:
10506     pic16_freeAsmop(result,NULL,ic,TRUE);
10507 }
10508
10509
10510
10511 /*-----------------------------------------------------------------*/
10512 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10513 /*-----------------------------------------------------------------*/
10514 static void genNearPointerGet (operand *left, 
10515                                operand *result, 
10516                                iCode *ic)
10517 {
10518   asmop *aop = NULL;
10519   //regs *preg = NULL ;
10520   sym_link *rtype, *retype;
10521   sym_link *ltype = operandType(left);    
10522
10523     FENTRY;
10524     
10525     rtype = operandType(result);
10526     retype= getSpec(rtype);
10527     
10528     pic16_aopOp(left,ic,FALSE);
10529
10530 //    pic16_DumpOp("(left)",left);
10531 //    pic16_DumpOp("(result)",result);
10532
10533     /* if left is rematerialisable and
10534      * result is not bit variable type and
10535      * the left is pointer to data space i.e
10536      * lower 128 bytes of space */
10537     
10538     if (AOP_TYPE(left) == AOP_PCODE
10539       && !IS_BITFIELD(retype)
10540       && DCL_TYPE(ltype) == POINTER) {
10541
10542         genDataPointerGet (left,result,ic);
10543         pic16_freeAsmop(left, NULL, ic, TRUE);
10544         return ;
10545     }
10546     
10547     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10548
10549     /* if the value is already in a pointer register
10550      * then don't need anything more */
10551     if (!AOP_INPREG(AOP(left))) {
10552       /* otherwise get a free pointer register */
10553       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10554                 
10555       /* VR -- the whole concept is to load FSR0 with the address of the symbol */
10556       /* bitfields will be handled by genUnpackBits */
10557       if(!IS_BITFIELD(retype)) {
10558
10559         if(is_LitAOp( AOP(left) )) {
10560           pic16_loadFSR0( left );
10561         } else {
10562             // set up FSR0 with address from left
10563             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10564             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10565         }
10566       }
10567     }
10568 //    else
10569 //    rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10570     
10571     pic16_aopOp (result,ic,FALSE);
10572     
10573     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10574
10575     /* if bitfield then unpack the bits */
10576     if (IS_BITFIELD(retype)) 
10577       genUnpackBits (result, left, NULL, POINTER);
10578     else {
10579       /* we have can just get the values */
10580       int size = AOP_SIZE(result);
10581       int offset = 0;   
10582         
10583       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10584
10585       /* fsr0 is loaded already -- VR */
10586 //      pic16_loadFSR0( left );
10587
10588 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
10589 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
10590       while(size--) {
10591         if(size) {
10592           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10593                 pic16_popGet(AOP(result), offset++)));
10594         } else {
10595           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10596                 pic16_popGet(AOP(result), offset++)));
10597         }
10598       }
10599 #if 0
10600 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
10601 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
10602       if(size)
10603         pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
10604 #endif
10605 /*
10606         while (size--) {
10607             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
10608
10609                 pic16_emitcode("mov","a,@%s",rname);
10610                 pic16_aopPut(AOP(result),"a",offset);
10611             } else {
10612                 sprintf(buffer,"@%s",rname);
10613                 pic16_aopPut(AOP(result),buffer,offset);
10614             }
10615             offset++ ;
10616             if (size)
10617                 pic16_emitcode("inc","%s",rname);
10618         }
10619 */
10620     }
10621
10622     /* now some housekeeping stuff */
10623     if (aop) {
10624       /* we had to allocate for this iCode */
10625       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10626       pic16_freeAsmop(NULL,aop,ic,TRUE);
10627     } else { 
10628       /* we did not allocate which means left
10629        * already in a pointer register, then
10630        * if size > 0 && this could be used again
10631        * we have to point it back to where it 
10632        * belongs */
10633       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10634       if (AOP_SIZE(result) > 1
10635         && !OP_SYMBOL(left)->remat
10636         && ( OP_SYMBOL(left)->liveTo > ic->seq
10637             || ic->depth )) {
10638 //        int size = AOP_SIZE(result) - 1;
10639 //        while (size--)
10640 //          pic16_emitcode("dec","%s",rname);
10641         }
10642     }
10643
10644     /* done */
10645     pic16_freeAsmop(left,NULL,ic,TRUE);
10646     pic16_freeAsmop(result,NULL,ic,TRUE);
10647 }
10648
10649 /*-----------------------------------------------------------------*/
10650 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10651 /*-----------------------------------------------------------------*/
10652 static void genPagedPointerGet (operand *left, 
10653                                operand *result, 
10654                                iCode *ic)
10655 {
10656     asmop *aop = NULL;
10657     regs *preg = NULL ;
10658     char *rname ;
10659     sym_link *rtype, *retype;    
10660
10661     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10662
10663     rtype = operandType(result);
10664     retype= getSpec(rtype);
10665     
10666     pic16_aopOp(left,ic,FALSE);
10667
10668   /* if the value is already in a pointer register
10669        then don't need anything more */
10670     if (!AOP_INPREG(AOP(left))) {
10671         /* otherwise get a free pointer register */
10672         aop = newAsmop(0);
10673         preg = getFreePtr(ic,&aop,FALSE);
10674         pic16_emitcode("mov","%s,%s",
10675                 preg->name,
10676                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10677         rname = preg->name ;
10678     } else
10679         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10680     
10681     pic16_freeAsmop(left,NULL,ic,TRUE);
10682     pic16_aopOp (result,ic,FALSE);
10683
10684     /* if bitfield then unpack the bits */
10685     if (IS_BITFIELD(retype)) 
10686         genUnpackBits (result,left,rname,PPOINTER);
10687     else {
10688         /* we have can just get the values */
10689         int size = AOP_SIZE(result);
10690         int offset = 0 ;        
10691         
10692         while (size--) {
10693             
10694             pic16_emitcode("movx","a,@%s",rname);
10695             pic16_aopPut(AOP(result),"a",offset);
10696             
10697             offset++ ;
10698             
10699             if (size)
10700                 pic16_emitcode("inc","%s",rname);
10701         }
10702     }
10703
10704     /* now some housekeeping stuff */
10705     if (aop) {
10706         /* we had to allocate for this iCode */
10707         pic16_freeAsmop(NULL,aop,ic,TRUE);
10708     } else { 
10709         /* we did not allocate which means left
10710            already in a pointer register, then
10711            if size > 0 && this could be used again
10712            we have to point it back to where it 
10713            belongs */
10714         if (AOP_SIZE(result) > 1 &&
10715             !OP_SYMBOL(left)->remat &&
10716             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10717               ic->depth )) {
10718             int size = AOP_SIZE(result) - 1;
10719             while (size--)
10720                 pic16_emitcode("dec","%s",rname);
10721         }
10722     }
10723
10724     /* done */
10725     pic16_freeAsmop(result,NULL,ic,TRUE);
10726     
10727         
10728 }
10729
10730 /*-----------------------------------------------------------------*/
10731 /* genFarPointerGet - gget value from far space                    */
10732 /*-----------------------------------------------------------------*/
10733 static void genFarPointerGet (operand *left,
10734                               operand *result, iCode *ic)
10735 {
10736     int size, offset ;
10737     sym_link *retype = getSpec(operandType(result));
10738
10739     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10740
10741     pic16_aopOp(left,ic,FALSE);
10742
10743     /* if the operand is already in dptr 
10744     then we do nothing else we move the value to dptr */
10745     if (AOP_TYPE(left) != AOP_STR) {
10746         /* if this is remateriazable */
10747         if (AOP_TYPE(left) == AOP_IMMD)
10748             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10749         else { /* we need to get it byte by byte */
10750             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10751             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10752             if (options.model == MODEL_FLAT24)
10753             {
10754                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10755             }
10756         }
10757     }
10758     /* so dptr know contains the address */
10759     pic16_freeAsmop(left,NULL,ic,TRUE);
10760     pic16_aopOp(result,ic,FALSE);
10761
10762     /* if bit then unpack */
10763     if (IS_BITFIELD(retype)) 
10764         genUnpackBits(result,left,"dptr",FPOINTER);
10765     else {
10766         size = AOP_SIZE(result);
10767         offset = 0 ;
10768
10769         while (size--) {
10770             pic16_emitcode("movx","a,@dptr");
10771             pic16_aopPut(AOP(result),"a",offset++);
10772             if (size)
10773                 pic16_emitcode("inc","dptr");
10774         }
10775     }
10776
10777     pic16_freeAsmop(result,NULL,ic,TRUE);
10778 }
10779 #if 0
10780 /*-----------------------------------------------------------------*/
10781 /* genCodePointerGet - get value from code space                  */
10782 /*-----------------------------------------------------------------*/
10783 static void genCodePointerGet (operand *left,
10784                                 operand *result, iCode *ic)
10785 {
10786     int size, offset ;
10787     sym_link *retype = getSpec(operandType(result));
10788
10789     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10790
10791     pic16_aopOp(left,ic,FALSE);
10792
10793     /* if the operand is already in dptr 
10794     then we do nothing else we move the value to dptr */
10795     if (AOP_TYPE(left) != AOP_STR) {
10796         /* if this is remateriazable */
10797         if (AOP_TYPE(left) == AOP_IMMD)
10798             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10799         else { /* we need to get it byte by byte */
10800             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10801             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10802             if (options.model == MODEL_FLAT24)
10803             {
10804                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10805             }
10806         }
10807     }
10808     /* so dptr know contains the address */
10809     pic16_freeAsmop(left,NULL,ic,TRUE);
10810     pic16_aopOp(result,ic,FALSE);
10811
10812     /* if bit then unpack */
10813     if (IS_BITFIELD(retype)) 
10814         genUnpackBits(result,left,"dptr",CPOINTER);
10815     else {
10816         size = AOP_SIZE(result);
10817         offset = 0 ;
10818
10819         while (size--) {
10820             pic16_emitcode("clr","a");
10821             pic16_emitcode("movc","a,@a+dptr");
10822             pic16_aopPut(AOP(result),"a",offset++);
10823             if (size)
10824                 pic16_emitcode("inc","dptr");
10825         }
10826     }
10827
10828     pic16_freeAsmop(result,NULL,ic,TRUE);
10829 }
10830 #endif
10831 #if 0
10832 /*-----------------------------------------------------------------*/
10833 /* genGenPointerGet - gget value from generic pointer space        */
10834 /*-----------------------------------------------------------------*/
10835 static void genGenPointerGet (operand *left,
10836                               operand *result, iCode *ic)
10837 {
10838   int size, offset, lit;
10839   sym_link *retype = getSpec(operandType(result));
10840
10841         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10842         pic16_aopOp(left,ic,FALSE);
10843         pic16_aopOp(result,ic,FALSE);
10844         size = AOP_SIZE(result);
10845
10846         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10847
10848         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
10849
10850                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
10851                 // load FSR0 from immediate
10852                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10853
10854 //              pic16_loadFSR0( left );
10855
10856                 offset = 0;
10857                 while(size--) {
10858                         if(size) {
10859                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10860                         } else {
10861                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10862                         }
10863                         offset++;
10864                 }
10865                 goto release;
10866
10867         }
10868         else { /* we need to get it byte by byte */
10869                 // set up FSR0 with address from left
10870                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10871                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10872
10873                 offset = 0 ;
10874
10875                 while(size--) {
10876                         if(size) {
10877                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10878                         } else {
10879                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10880                         }
10881                         offset++;
10882                 }
10883                 goto release;
10884         }
10885
10886   /* if bit then unpack */
10887         if (IS_BITFIELD(retype)) 
10888                 genUnpackBits(result,left,"BAD",GPOINTER);
10889
10890         release:
10891         pic16_freeAsmop(left,NULL,ic,TRUE);
10892         pic16_freeAsmop(result,NULL,ic,TRUE);
10893
10894 }
10895 #endif
10896
10897
10898 /*-----------------------------------------------------------------*/
10899 /* genGenPointerGet - gget value from generic pointer space        */
10900 /*-----------------------------------------------------------------*/
10901 static void genGenPointerGet (operand *left,
10902                               operand *result, iCode *ic)
10903 {
10904   int size, offset, lit;
10905   sym_link *retype = getSpec(operandType(result));
10906   char fgptrget[32];
10907
10908     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10909     pic16_aopOp(left,ic,FALSE);
10910     pic16_aopOp(result,ic,FALSE);
10911     size = AOP_SIZE(result);
10912
10913     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10914
10915     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
10916
10917       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
10918       // load FSR0 from immediate
10919       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10920
10921       werror(W_POSSBUG2, __FILE__, __LINE__);
10922
10923       offset = 0;
10924       while(size--) {
10925         if(size) {
10926           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10927         } else {
10928           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10929         }
10930         offset++;
10931       }
10932
10933       goto release;
10934
10935     } else { /* we need to get it byte by byte */
10936
10937       /* set up WREG:PRODL:FSR0L with address from left */
10938       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10939       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
10940       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
10941       
10942       switch( size ) {
10943         case 1: strcpy(fgptrget, "__gptrget1"); break;
10944         case 2: strcpy(fgptrget, "__gptrget2"); break;
10945         case 3: strcpy(fgptrget, "__gptrget3"); break;
10946         case 4: strcpy(fgptrget, "__gptrget4"); break;
10947         default:
10948           werror(W_POSSBUG2, __FILE__, __LINE__);
10949           abort();
10950       }
10951       
10952       pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
10953       
10954       assignResultValue(result, 1);
10955       
10956       {
10957         symbol *sym;
10958
10959           sym = newSymbol( fgptrget, 0 );
10960           strcpy(sym->rname, fgptrget);
10961           checkAddSym(&externs, sym);
10962
10963 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
10964       }
10965               
10966       goto release;
10967     }
10968
10969   /* if bit then unpack */
10970     if (IS_BITFIELD(retype)) 
10971       genUnpackBits(result,left,"BAD",GPOINTER);
10972
10973 release:
10974   pic16_freeAsmop(left,NULL,ic,TRUE);
10975   pic16_freeAsmop(result,NULL,ic,TRUE);
10976 }
10977
10978 /*-----------------------------------------------------------------*/
10979 /* genConstPointerGet - get value from const generic pointer space */
10980 /*-----------------------------------------------------------------*/
10981 static void genConstPointerGet (operand *left,
10982                                 operand *result, iCode *ic)
10983 {
10984   //sym_link *retype = getSpec(operandType(result));
10985   // symbol *albl = newiTempLabel(NULL);        // patch 15
10986   // symbol *blbl = newiTempLabel(NULL);        //
10987   // PIC_OPCODE poc;                            // patch 15
10988   int size;
10989   int offset = 0;
10990
10991   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10992   pic16_aopOp(left,ic,FALSE);
10993   pic16_aopOp(result,ic,TRUE);
10994   size = AOP_SIZE(result);
10995
10996   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10997
10998   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
10999 #if 0                                                                   // patch 15
11000   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
11001   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
11002   pic16_emitpLabel(albl->key);
11003
11004   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
11005   
11006   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
11007   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
11008   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
11009   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
11010   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
11011
11012   pic16_emitpLabel(blbl->key);
11013
11014   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
11015 #endif                                                                  // patch 15
11016
11017
11018   // set up table pointer
11019   if( (AOP_TYPE(left) == AOP_PCODE) 
11020       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11021           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
11022     {
11023       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11024       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11025       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11026       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11027       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11028       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11029     }
11030   else
11031     {
11032       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11033       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11034       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11035     }
11036
11037
11038   while(size--)
11039     {
11040       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11041       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11042       offset++;
11043     }
11044     
11045   pic16_freeAsmop(left,NULL,ic,TRUE);
11046   pic16_freeAsmop(result,NULL,ic,TRUE);
11047
11048 }
11049
11050
11051 /*-----------------------------------------------------------------*/
11052 /* genPointerGet - generate code for pointer get                   */
11053 /*-----------------------------------------------------------------*/
11054 static void genPointerGet (iCode *ic)
11055 {
11056     operand *left, *result ;
11057     sym_link *type, *etype;
11058     int p_type;
11059
11060     FENTRY;
11061     
11062     left = IC_LEFT(ic);
11063     result = IC_RESULT(ic) ;
11064
11065     /* depending on the type of pointer we need to
11066     move it to the correct pointer register */
11067     type = operandType(left);
11068     etype = getSpec(type);
11069
11070 #if 0
11071     if (IS_PTR_CONST(type))
11072 #else
11073     if (IS_CODEPTR(type))
11074 #endif
11075       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11076
11077     /* if left is of type of pointer then it is simple */
11078     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11079         p_type = DCL_TYPE(type);
11080     else {
11081         /* we have to go by the storage class */
11082         p_type = PTR_TYPE(SPEC_OCLS(etype));
11083
11084         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11085
11086         if (SPEC_OCLS(etype)->codesp ) {
11087           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11088           //p_type = CPOINTER ; 
11089         }
11090         else
11091             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
11092               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11093                /*p_type = FPOINTER ;*/ 
11094             else
11095                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
11096                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11097 /*                  p_type = PPOINTER; */
11098                 else
11099                     if (SPEC_OCLS(etype) == idata )
11100                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11101 /*                      p_type = IPOINTER; */
11102                     else
11103                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11104 /*                      p_type = POINTER ; */
11105     }
11106
11107     /* now that we have the pointer type we assign
11108     the pointer values */
11109     switch (p_type) {
11110
11111     case POINTER:       
11112     case IPOINTER:
11113         genNearPointerGet (left,result,ic);
11114         break;
11115
11116     case PPOINTER:
11117         genPagedPointerGet(left,result,ic);
11118         break;
11119
11120     case FPOINTER:
11121         genFarPointerGet (left,result,ic);
11122         break;
11123
11124     case CPOINTER:
11125         genConstPointerGet (left,result,ic);
11126         //pic16_emitcodePointerGet (left,result,ic);
11127         break;
11128
11129     case GPOINTER:
11130 #if 0
11131       if (IS_PTR_CONST(type))
11132         genConstPointerGet (left,result,ic);
11133       else
11134 #endif
11135         genGenPointerGet (left,result,ic);
11136       break;
11137
11138     default:
11139       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11140               "genPointerGet: illegal pointer type");
11141     
11142     }
11143
11144 }
11145
11146 /*-----------------------------------------------------------------*/
11147 /* genPackBits - generates code for packed bit storage             */
11148 /*-----------------------------------------------------------------*/
11149 static void genPackBits (sym_link    *etype , operand *result,
11150                          operand *right ,
11151                          char *rname, int p_type)
11152 {
11153   int shCnt = 0 ;
11154   int offset = 0  ;
11155   int rLen = 0 ;
11156   int blen, bstr ;   
11157   sym_link *retype;
11158   char *l ;
11159
11160         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11161         blen = SPEC_BLEN(etype);
11162         bstr = SPEC_BSTR(etype);
11163
11164         retype = getSpec(operandType(right));
11165
11166         if(AOP_TYPE(right) == AOP_LIT) {
11167                 if((blen == 1) && (bstr < 8)) {
11168                   unsigned long lit;
11169                         /* it is a single bit, so use the appropriate bit instructions */
11170
11171                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11172
11173                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11174 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11175                         if((p_type == POINTER) && (result)) {
11176                                 /* workaround to reduce the extra lfsr instruction */
11177                                 if(lit) {
11178                                         pic16_emitpcode(POC_BSF,
11179                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11180                                 } else {
11181                                         pic16_emitpcode(POC_BCF,
11182                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11183                                 }
11184                         } else {
11185                                 pic16_loadFSR0( result );
11186                                 if(lit) {
11187                                         pic16_emitpcode(POC_BSF,
11188                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11189                                 } else {
11190                                         pic16_emitpcode(POC_BCF,
11191                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11192                                 }
11193                         }
11194         
11195                   return;
11196                 }
11197
11198                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11199                 offset++;
11200         } else
11201         if(IS_BITFIELD(retype) 
11202           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11203           && (blen == 1)) {
11204           int rblen, rbstr;
11205
11206             rblen = SPEC_BLEN( retype );
11207             rbstr = SPEC_BSTR( retype );
11208             
11209
11210             if(IS_BITFIELD(etype)) {
11211               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11212               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11213             } else {
11214               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11215             }
11216             
11217             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11218             
11219             if(IS_BITFIELD(etype)) {
11220               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11221             } else {
11222               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11223             }
11224
11225             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11226             
11227             return;
11228         } else
11229           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11230
11231         /* if the bit lenth is less than or    */
11232         /* it exactly fits a byte then         */
11233         if((shCnt=SPEC_BSTR(etype))
11234                 || SPEC_BLEN(etype) <= 8 )  {
11235
11236                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11237
11238                 /* shift left acc */
11239                 AccLsh(shCnt);
11240
11241                 /* using PRODL as a temporary register here */
11242                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11243
11244                 switch (p_type) {
11245                         case FPOINTER:
11246                         case POINTER:
11247                                 pic16_loadFSR0( result );
11248                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11249 //                              pic16_emitcode ("mov","b,a");
11250 //                              pic16_emitcode("mov","a,@%s",rname);
11251                                 break;
11252
11253                         case GPOINTER:
11254                                 werror(W_POSSBUG2, __FILE__, __LINE__);
11255                                 break;
11256
11257                 }
11258 #if 1
11259                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11260                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11261                                         (unsigned char)(0xff >> (8-bstr))) ));
11262                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
11263                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11264 #endif
11265
11266           return;
11267         }
11268
11269
11270         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11271         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11272         exit(-1);
11273
11274
11275     /* if we r done */
11276     if ( SPEC_BLEN(etype) <= 8 )
11277         return ;
11278
11279     pic16_emitcode("inc","%s",rname);
11280     rLen = SPEC_BLEN(etype) ;     
11281
11282
11283
11284     /* now generate for lengths greater than one byte */
11285     while (1) {
11286
11287         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
11288
11289         rLen -= 8 ;
11290         if (rLen <= 0 )
11291             break ;
11292
11293         switch (p_type) {
11294             case POINTER:
11295                 if (*l == '@') {
11296                     MOVA(l);
11297                     pic16_emitcode("mov","@%s,a",rname);
11298                 } else
11299                     pic16_emitcode("mov","@%s,%s",rname,l);
11300                 break;
11301
11302             case FPOINTER:
11303                 MOVA(l);
11304                 pic16_emitcode("movx","@dptr,a");
11305                 break;
11306
11307             case GPOINTER:
11308                 MOVA(l);
11309                 DEBUGpic16_emitcode(";lcall","__gptrput");
11310                 break;  
11311         }   
11312         pic16_emitcode ("inc","%s",rname);
11313     }
11314
11315     MOVA(l);
11316
11317     /* last last was not complete */
11318     if (rLen)   {
11319         /* save the byte & read byte */
11320         switch (p_type) {
11321             case POINTER:
11322                 pic16_emitcode ("mov","b,a");
11323                 pic16_emitcode("mov","a,@%s",rname);
11324                 break;
11325
11326             case FPOINTER:
11327                 pic16_emitcode ("mov","b,a");
11328                 pic16_emitcode("movx","a,@dptr");
11329                 break;
11330
11331             case GPOINTER:
11332                 pic16_emitcode ("push","b");
11333                 pic16_emitcode ("push","acc");
11334                 pic16_emitcode ("lcall","__gptrget");
11335                 pic16_emitcode ("pop","b");
11336                 break;
11337         }
11338
11339         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11340         pic16_emitcode ("orl","a,b");
11341     }
11342
11343     if (p_type == GPOINTER)
11344         pic16_emitcode("pop","b");
11345
11346     switch (p_type) {
11347
11348     case POINTER:
11349         pic16_emitcode("mov","@%s,a",rname);
11350         break;
11351         
11352     case FPOINTER:
11353         pic16_emitcode("movx","@dptr,a");
11354         break;
11355         
11356     case GPOINTER:
11357         DEBUGpic16_emitcode(";lcall","__gptrput");
11358         break;                  
11359     }
11360 }
11361 /*-----------------------------------------------------------------*/
11362 /* genDataPointerSet - remat pointer to data space                 */
11363 /*-----------------------------------------------------------------*/
11364 static void genDataPointerSet(operand *right,
11365                               operand *result,
11366                               iCode *ic)
11367 {
11368     int size, offset = 0, resoffset=0 ;
11369
11370     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11371     pic16_aopOp(right,ic,FALSE);
11372
11373     size = AOP_SIZE(right);
11374
11375 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11376
11377 #if 0
11378     if ( AOP_TYPE(result) == AOP_PCODE) {
11379       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11380               AOP(result)->aopu.pcop->name,
11381                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11382               PCOR(AOP(result)->aopu.pcop)->instance:
11383               PCOI(AOP(result)->aopu.pcop)->offset);
11384     }
11385 #endif
11386
11387         if(AOP(result)->aopu.pcop->type == PO_DIR)
11388                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11389
11390         while (size--) {
11391                 if (AOP_TYPE(right) == AOP_LIT) {
11392                   unsigned int lit;
11393
11394                     if(!IS_FLOAT(operandType( right )))
11395                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11396                     else {
11397                       union {
11398                         unsigned long lit_int;
11399                         float lit_float;
11400                       } info;
11401         
11402                         /* take care if literal is a float */
11403                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11404                         lit = info.lit_int;
11405                     }
11406
11407                     lit = lit >> (8*offset);
11408                     if(lit&0xff) {
11409                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11410                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11411                     } else {
11412                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11413                     }
11414                 } else {
11415                   mov2w(AOP(right), offset);
11416                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11417                 }
11418                 offset++;
11419                 resoffset++;
11420         }
11421
11422     pic16_freeAsmop(right,NULL,ic,TRUE);
11423 }
11424
11425
11426
11427 /*-----------------------------------------------------------------*/
11428 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11429 /*-----------------------------------------------------------------*/
11430 static void genNearPointerSet (operand *right,
11431                                operand *result, 
11432                                iCode *ic)
11433 {
11434   asmop *aop = NULL;
11435   char *l;
11436   sym_link *retype;
11437   sym_link *ptype = operandType(result);
11438   sym_link *resetype;
11439     
11440         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11441         retype= getSpec(operandType(right));
11442         resetype = getSpec(operandType(result));
11443   
11444         pic16_aopOp(result,ic,FALSE);
11445     
11446         /* if the result is rematerializable &
11447          * in data space & not a bit variable */
11448         
11449         /* and result is not a bit variable */
11450         if (AOP_TYPE(result) == AOP_PCODE
11451 //              && AOP_TYPE(result) == AOP_IMMD
11452                 && DCL_TYPE(ptype) == POINTER
11453                 && !IS_BITFIELD(retype)
11454                 && !IS_BITFIELD(resetype)) {
11455
11456                 genDataPointerSet (right,result,ic);
11457                 pic16_freeAsmop(result,NULL,ic,TRUE);
11458           return;
11459         }
11460
11461         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11462         pic16_aopOp(right,ic,FALSE);
11463         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11464
11465         /* if the value is already in a pointer register
11466          * then don't need anything more */
11467         if (!AOP_INPREG(AOP(result))) {
11468                 /* otherwise get a free pointer register */
11469                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11470
11471 //              if( (AOP_TYPE(result) == AOP_PCODE) 
11472 //                      && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
11473 //                              || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
11474                 if(is_LitAOp( AOP(result) ))
11475                 {
11476                   if(!IS_BITFIELD(resetype))
11477                         pic16_loadFSR0( result );  // patch 10
11478                 } else {
11479                   if(!IS_BITFIELD(resetype)) {
11480                         // set up FSR0 with address of result
11481                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11482                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11483                   }
11484                 }
11485
11486         }
11487 //      else
11488 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11489
11490         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11491
11492 //      pic16_loadFSR0( result );
11493
11494         /* if bitfield then unpack the bits */
11495         if (IS_BITFIELD(resetype)) {
11496                 genPackBits (resetype, result, right, NULL, POINTER);
11497         } else {
11498                 /* we have can just get the values */
11499           int size = AOP_SIZE(right);
11500           int offset = 0 ;    
11501
11502                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11503                 while (size--) {
11504                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11505                         if (*l == '@' ) {
11506                                 //MOVA(l);
11507                                 //pic16_emitcode("mov","@%s,a",rname);
11508                                 pic16_emitcode("movf","indf0,w ;1");
11509                         } else {
11510
11511                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
11512                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
11513                                         if (size) {                                                                     // 
11514                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
11515                                         } else {                                                                        // 
11516                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
11517                                         }                                                                               // 
11518                                 } else { // no literal                                                                  // 
11519                                         if(size) {                                                                      // 
11520                                                 pic16_emitpcode(POC_MOVFF,                                              // 
11521                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
11522                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
11523                                         } else {                                                                        // 
11524                                                 pic16_emitpcode(POC_MOVFF,                                              // 
11525                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
11526                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
11527                                         }                                                                               //
11528                                 }                                                                                       // patch 10
11529                         }
11530                         offset++;
11531                 }
11532         }
11533
11534         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11535         /* now some housekeeping stuff */
11536         if (aop) {
11537                 /* we had to allocate for this iCode */
11538                 pic16_freeAsmop(NULL,aop,ic,TRUE);
11539         } else { 
11540                 /* we did not allocate which means left
11541                  * already in a pointer register, then
11542                  * if size > 0 && this could be used again
11543                  * we have to point it back to where it 
11544                  * belongs */
11545                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11546                 if (AOP_SIZE(right) > 1
11547                         && !OP_SYMBOL(result)->remat
11548                         && ( OP_SYMBOL(result)->liveTo > ic->seq
11549                                 || ic->depth )) {
11550
11551                   int size = AOP_SIZE(right) - 1;
11552
11553                         while (size--)
11554                                 pic16_emitcode("decf","fsr0,f");
11555                         //pic16_emitcode("dec","%s",rname);
11556                 }
11557         }
11558
11559         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11560         /* done */
11561 //release:
11562         pic16_freeAsmop(right,NULL,ic,TRUE);
11563         pic16_freeAsmop(result,NULL,ic,TRUE);
11564 }
11565
11566 /*-----------------------------------------------------------------*/
11567 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11568 /*-----------------------------------------------------------------*/
11569 static void genPagedPointerSet (operand *right,
11570                                operand *result, 
11571                                iCode *ic)
11572 {
11573     asmop *aop = NULL;
11574     regs *preg = NULL ;
11575     char *rname , *l;
11576     sym_link *retype;
11577        
11578     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11579
11580     retype= getSpec(operandType(right));
11581     
11582     pic16_aopOp(result,ic,FALSE);
11583     
11584     /* if the value is already in a pointer register
11585        then don't need anything more */
11586     if (!AOP_INPREG(AOP(result))) {
11587         /* otherwise get a free pointer register */
11588         aop = newAsmop(0);
11589         preg = getFreePtr(ic,&aop,FALSE);
11590         pic16_emitcode("mov","%s,%s",
11591                 preg->name,
11592                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11593         rname = preg->name ;
11594     } else
11595         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11596     
11597     pic16_freeAsmop(result,NULL,ic,TRUE);
11598     pic16_aopOp (right,ic,FALSE);
11599
11600     /* if bitfield then unpack the bits */
11601     if (IS_BITFIELD(retype)) 
11602         genPackBits (retype,result,right,rname,PPOINTER);
11603     else {
11604         /* we have can just get the values */
11605         int size = AOP_SIZE(right);
11606         int offset = 0 ;        
11607         
11608         while (size--) {
11609             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11610             
11611             MOVA(l);
11612             pic16_emitcode("movx","@%s,a",rname);
11613
11614             if (size)
11615                 pic16_emitcode("inc","%s",rname);
11616
11617             offset++;
11618         }
11619     }
11620     
11621     /* now some housekeeping stuff */
11622     if (aop) {
11623         /* we had to allocate for this iCode */
11624         pic16_freeAsmop(NULL,aop,ic,TRUE);
11625     } else { 
11626         /* we did not allocate which means left
11627            already in a pointer register, then
11628            if size > 0 && this could be used again
11629            we have to point it back to where it 
11630            belongs */
11631         if (AOP_SIZE(right) > 1 &&
11632             !OP_SYMBOL(result)->remat &&
11633             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11634               ic->depth )) {
11635             int size = AOP_SIZE(right) - 1;
11636             while (size--)
11637                 pic16_emitcode("dec","%s",rname);
11638         }
11639     }
11640
11641     /* done */
11642     pic16_freeAsmop(right,NULL,ic,TRUE);
11643     
11644         
11645 }
11646
11647 /*-----------------------------------------------------------------*/
11648 /* genFarPointerSet - set value from far space                     */
11649 /*-----------------------------------------------------------------*/
11650 static void genFarPointerSet (operand *right,
11651                               operand *result, iCode *ic)
11652 {
11653     int size, offset ;
11654     sym_link *retype = getSpec(operandType(right));
11655
11656     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11657     pic16_aopOp(result,ic,FALSE);
11658
11659     /* if the operand is already in dptr 
11660     then we do nothing else we move the value to dptr */
11661     if (AOP_TYPE(result) != AOP_STR) {
11662         /* if this is remateriazable */
11663         if (AOP_TYPE(result) == AOP_IMMD)
11664             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11665         else { /* we need to get it byte by byte */
11666             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11667             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11668             if (options.model == MODEL_FLAT24)
11669             {
11670                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11671             }
11672         }
11673     }
11674     /* so dptr know contains the address */
11675     pic16_freeAsmop(result,NULL,ic,TRUE);
11676     pic16_aopOp(right,ic,FALSE);
11677
11678     /* if bit then unpack */
11679     if (IS_BITFIELD(retype)) 
11680         genPackBits(retype,result,right,"dptr",FPOINTER);
11681     else {
11682         size = AOP_SIZE(right);
11683         offset = 0 ;
11684
11685         while (size--) {
11686             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11687             MOVA(l);
11688             pic16_emitcode("movx","@dptr,a");
11689             if (size)
11690                 pic16_emitcode("inc","dptr");
11691         }
11692     }
11693
11694     pic16_freeAsmop(right,NULL,ic,TRUE);
11695 }
11696
11697 /*-----------------------------------------------------------------*/
11698 /* genGenPointerSet - set value from generic pointer space         */
11699 /*-----------------------------------------------------------------*/
11700 #if 0
11701 static void genGenPointerSet (operand *right,
11702                               operand *result, iCode *ic)
11703 {
11704         int i, size, offset, lit;
11705         sym_link *retype = getSpec(operandType(right));
11706
11707         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11708
11709         pic16_aopOp(result,ic,FALSE);
11710         pic16_aopOp(right,ic,FALSE);
11711         size = AOP_SIZE(right);
11712         offset = 0;
11713
11714         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11715
11716         /* if the operand is already in dptr 
11717                 then we do nothing else we move the value to dptr */
11718         if (AOP_TYPE(result) != AOP_STR) {
11719                 /* if this is remateriazable */
11720                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11721                 // WARNING: anythig until "else" is untested!
11722                 if (AOP_TYPE(result) == AOP_IMMD) {
11723                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11724                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11725                         // load FSR0 from immediate
11726                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11727                         offset = 0;
11728                         while(size--) {
11729                                 if(size) {
11730                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11731                                 } else {
11732                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11733                                 }
11734                                 offset++;
11735                         }
11736                         goto release;
11737                 }
11738                 else { /* we need to get it byte by byte */
11739                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11740                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11741
11742                         // set up FSR0 with address of result
11743                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11744                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11745
11746                         /* hack hack! see if this the FSR. If so don't load W */
11747                         if(AOP_TYPE(right) != AOP_ACC) {
11748
11749                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11750
11751                                 if(AOP_TYPE(right) == AOP_LIT)
11752                                 {
11753                                         // copy literal
11754                                         // note: pic16_popGet handles sign extension
11755                                         for(i=0;i<size;i++) {
11756                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11757                                                 if(i < size-1)
11758                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11759                                                 else
11760                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11761                                         }
11762                                 } else {
11763                                         // copy regs
11764
11765                                         for(i=0;i<size;i++) {
11766                                                 if(i < size-1)
11767                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11768                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11769                                                 else
11770                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11771                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11772                                         }
11773                                 }
11774                                 goto release;
11775                         } 
11776                         // right = ACC
11777                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11778                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11779                         goto release;
11780         } // if (AOP_TYPE(result) != AOP_IMMD)
11781
11782         } // if (AOP_TYPE(result) != AOP_STR)
11783         /* so dptr know contains the address */
11784
11785
11786         /* if bit then unpack */
11787         if (IS_BITFIELD(retype)) 
11788                 genPackBits(retype,result,right,"dptr",GPOINTER);
11789         else {
11790                 size = AOP_SIZE(right);
11791                 offset = 0 ;
11792
11793                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11794
11795                 // set up FSR0 with address of result
11796                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11797                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11798         
11799                 while (size--) {
11800                         if (AOP_TYPE(right) == AOP_LIT) {
11801                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11802                                 if (size) {
11803                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11804                                 } else {
11805                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11806                                 }
11807                         } else { // no literal
11808                                 if(size) {
11809                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11810                                 } else {
11811                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11812                                 }
11813                         }
11814                         offset++;
11815                 }
11816         }
11817
11818         release:
11819         pic16_freeAsmop(right,NULL,ic,TRUE);
11820         pic16_freeAsmop(result,NULL,ic,TRUE);
11821 }
11822 #endif
11823
11824 static void genGenPointerSet (operand *right,
11825                               operand *result, iCode *ic)
11826 {
11827   int size;
11828   sym_link *retype = getSpec(operandType(right));
11829   char fgptrput[32];
11830
11831     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11832
11833     pic16_aopOp(result,ic,FALSE);
11834     pic16_aopOp(right,ic,FALSE);
11835     size = AOP_SIZE(right);
11836
11837     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11838
11839
11840     /* if bit then unpack */
11841     if (IS_BITFIELD(retype)) {
11842 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11843       genPackBits(retype,result,right,"dptr",GPOINTER);
11844       goto release;
11845     }
11846
11847     size = AOP_SIZE(right);
11848
11849     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11850
11851
11852
11853     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
11854
11855     /* value of right+0 is placed on stack, which will be retrieved
11856      * by the support function this restoring the stack. The important
11857      * thing is that there is no need to manually restore stack pointer
11858      * here */
11859     pushaop(AOP(right), 0);
11860 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
11861     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
11862     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
11863     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
11864     
11865     /* load address to write to in WREG:FSR0H:FSR0L */
11866     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
11867                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
11868     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
11869                                 pic16_popCopyReg(&pic16_pc_prodl)));
11870     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
11871     
11872
11873     /* put code here */
11874     switch (size) {
11875       case 1: strcpy(fgptrput, "__gptrput1"); break;
11876       case 2: strcpy(fgptrput, "__gptrput2"); break;
11877       case 3: strcpy(fgptrput, "__gptrput3"); break;
11878       case 4: strcpy(fgptrput, "__gptrput4"); break;
11879       default:
11880         werror(W_POSSBUG2, __FILE__, __LINE__);
11881         abort();
11882     }
11883     
11884     pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
11885     
11886     {
11887       symbol *sym;
11888                   
11889         sym = newSymbol( fgptrput, 0 );
11890         strcpy(sym->rname, fgptrput);
11891         checkAddSym(&externs, sym);
11892     }
11893
11894 release:
11895     pic16_freeAsmop(right,NULL,ic,TRUE);
11896     pic16_freeAsmop(result,NULL,ic,TRUE);
11897 }
11898
11899 /*-----------------------------------------------------------------*/
11900 /* genPointerSet - stores the value into a pointer location        */
11901 /*-----------------------------------------------------------------*/
11902 static void genPointerSet (iCode *ic)
11903 {    
11904   operand *right, *result ;
11905   sym_link *type, *etype;
11906   int p_type;
11907
11908     FENTRY;
11909
11910     right = IC_RIGHT(ic);
11911     result = IC_RESULT(ic) ;
11912
11913     /* depending on the type of pointer we need to
11914     move it to the correct pointer register */
11915     type = operandType(result);
11916     etype = getSpec(type);
11917     /* if left is of type of pointer then it is simple */
11918     if (IS_PTR(type) && !IS_FUNC(type->next)) {
11919         p_type = DCL_TYPE(type);
11920     }
11921     else {
11922         /* we have to go by the storage class */
11923         p_type = PTR_TYPE(SPEC_OCLS(etype));
11924
11925 /*      if (SPEC_OCLS(etype)->codesp ) { */
11926 /*          p_type = CPOINTER ;  */
11927 /*      } */
11928 /*      else */
11929 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11930 /*              p_type = FPOINTER ; */
11931 /*          else */
11932 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11933 /*                  p_type = PPOINTER ; */
11934 /*              else */
11935 /*                  if (SPEC_OCLS(etype) == idata ) */
11936 /*                      p_type = IPOINTER ; */
11937 /*                  else */
11938 /*                      p_type = POINTER ; */
11939     }
11940
11941     /* now that we have the pointer type we assign
11942     the pointer values */
11943     switch (p_type) {
11944
11945     case POINTER:
11946     case IPOINTER:
11947         genNearPointerSet (right,result,ic);
11948         break;
11949
11950     case PPOINTER:
11951         genPagedPointerSet (right,result,ic);
11952         break;
11953
11954     case FPOINTER:
11955         genFarPointerSet (right,result,ic);
11956         break;
11957
11958     case GPOINTER:
11959         genGenPointerSet (right,result,ic);
11960         break;
11961
11962     default:
11963       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11964               "genPointerSet: illegal pointer type");
11965     }
11966 }
11967
11968 /*-----------------------------------------------------------------*/
11969 /* genIfx - generate code for Ifx statement                        */
11970 /*-----------------------------------------------------------------*/
11971 static void genIfx (iCode *ic, iCode *popIc)
11972 {
11973   operand *cond = IC_COND(ic);
11974   int isbit =0;
11975
11976     FENTRY;
11977
11978     pic16_aopOp(cond,ic,FALSE);
11979
11980     /* get the value into acc */
11981     if (AOP_TYPE(cond) != AOP_CRY)
11982       pic16_toBoolean(cond);
11983     else
11984       isbit = 1;
11985     /* the result is now in the accumulator */
11986     pic16_freeAsmop(cond,NULL,ic,TRUE);
11987
11988     /* if there was something to be popped then do it */
11989     if (popIc)
11990       genIpop(popIc);
11991
11992     /* if the condition is  a bit variable */
11993     if (isbit && IS_ITEMP(cond) && 
11994         SPIL_LOC(cond)) {
11995       genIfxJump(ic,SPIL_LOC(cond)->rname);
11996       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
11997     } else {
11998       if (isbit && !IS_ITEMP(cond))
11999         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12000         else
12001         genIfxJump(ic,"a");
12002     }
12003     ic->generated = 1;
12004 }
12005
12006 /*-----------------------------------------------------------------*/
12007 /* genAddrOf - generates code for address of                       */
12008 /*-----------------------------------------------------------------*/
12009 static void genAddrOf (iCode *ic)
12010 {
12011   operand *result, *left;
12012   int size;
12013   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12014   pCodeOp *pcop0, *pcop1, *pcop2;
12015
12016     FENTRY;
12017
12018     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12019
12020     sym = OP_SYMBOL( IC_LEFT(ic) );
12021     
12022     if(sym->onStack) {
12023       /* get address of symbol on stack */
12024       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12025 #if 0
12026       fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12027                   OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12028 #endif
12029
12030       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
12031                       pic16_popCopyReg(&pic16_pc_fsr2l),
12032                       pic16_popGet(AOP(result), 0)));
12033       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
12034                       pic16_popCopyReg(&pic16_pc_fsr2h),
12035                       pic16_popGet(AOP(result), 1)));
12036      
12037       // operands on stack are accessible via "FSR2 - index" with index starting at 0 for the first operand
12038       pic16_emitpcode(POC_MOVLW, pic16_popGetLit( - (OP_SYMBOL( IC_LEFT(ic))->stack + 1 ) /*+ _G.stack_lat*/));
12039       pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(result), 0));
12040       emitSKPC;
12041       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result), 1));
12042
12043       goto release;
12044     }
12045         
12046 //      if(pic16_debug_verbose) {
12047 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12048 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12049 //      }
12050         
12051     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12052     size = AOP_SIZE(IC_RESULT(ic));
12053
12054
12055     /* Assume that what we want the address of is in data space
12056      * since there is no stack on the PIC, yet! -- VR */
12057   
12058     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12059     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12060     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12061         
12062     if (size == 3) {
12063       pic16_emitpcode(POC_MOVLW, pcop0);
12064       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12065       pic16_emitpcode(POC_MOVLW, pcop1);
12066       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12067       pic16_emitpcode(POC_MOVLW, pcop2);
12068       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12069     } else
12070     if (size == 2) {
12071       pic16_emitpcode(POC_MOVLW, pcop0);
12072       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12073       pic16_emitpcode(POC_MOVLW, pcop1);
12074     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12075     } else {
12076       pic16_emitpcode(POC_MOVLW, pcop0);
12077       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12078     }
12079
12080     pic16_freeAsmop(left, NULL, ic, FALSE);
12081 release:
12082     pic16_freeAsmop(result,NULL,ic,TRUE);
12083 }
12084
12085
12086 #if 0
12087 /*-----------------------------------------------------------------*/
12088 /* genFarFarAssign - assignment when both are in far space         */
12089 /*-----------------------------------------------------------------*/
12090 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12091 {
12092     int size = AOP_SIZE(right);
12093     int offset = 0;
12094     char *l ;
12095     /* first push the right side on to the stack */
12096     while (size--) {
12097         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12098         MOVA(l);
12099         pic16_emitcode ("push","acc");
12100     }
12101     
12102     pic16_freeAsmop(right,NULL,ic,FALSE);
12103     /* now assign DPTR to result */
12104     pic16_aopOp(result,ic,FALSE);
12105     size = AOP_SIZE(result);
12106     while (size--) {
12107         pic16_emitcode ("pop","acc");
12108         pic16_aopPut(AOP(result),"a",--offset);
12109     }
12110     pic16_freeAsmop(result,NULL,ic,FALSE);
12111         
12112 }
12113 #endif
12114
12115 /*-----------------------------------------------------------------*/
12116 /* genAssign - generate code for assignment                        */
12117 /*-----------------------------------------------------------------*/
12118 static void genAssign (iCode *ic)
12119 {
12120   operand *result, *right;
12121   int size, offset,know_W;
12122   unsigned long lit = 0L;
12123
12124   result = IC_RESULT(ic);
12125   right  = IC_RIGHT(ic) ;
12126
12127   FENTRY;
12128   
12129   /* if they are the same */
12130   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12131     return ;
12132
12133   /* reversed order operands are aopOp'ed so that result operand
12134    * is effective in case right is a stack symbol. This maneauver
12135    * allows to use the _G.resDirect flag later */
12136   pic16_aopOp(result,ic,TRUE);
12137   pic16_aopOp(right,ic,FALSE);
12138
12139   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12140
12141   /* if they are the same registers */
12142   if (pic16_sameRegs(AOP(right),AOP(result)))
12143     goto release;
12144
12145   /* if the result is a bit */
12146   if (AOP_TYPE(result) == AOP_CRY) {
12147     /* if the right size is a literal then
12148        we know what the value is */
12149     if (AOP_TYPE(right) == AOP_LIT) {
12150           
12151       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12152                   pic16_popGet(AOP(result),0));
12153
12154       if (((int) operandLitValue(right))) 
12155         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12156                        AOP(result)->aopu.aop_dir,
12157                        AOP(result)->aopu.aop_dir);
12158       else
12159         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12160                        AOP(result)->aopu.aop_dir,
12161                        AOP(result)->aopu.aop_dir);
12162       goto release;
12163     }
12164
12165     /* the right is also a bit variable */
12166     if (AOP_TYPE(right) == AOP_CRY) {
12167       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12168       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12169       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12170
12171       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12172                      AOP(result)->aopu.aop_dir,
12173                      AOP(result)->aopu.aop_dir);
12174       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12175                      AOP(right)->aopu.aop_dir,
12176                      AOP(right)->aopu.aop_dir);
12177       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12178                      AOP(result)->aopu.aop_dir,
12179                      AOP(result)->aopu.aop_dir);
12180       goto release ;
12181     }
12182
12183     /* we need to or */
12184     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12185     pic16_toBoolean(right);
12186     emitSKPZ;
12187     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12188     //pic16_aopPut(AOP(result),"a",0);
12189     goto release ;
12190   }
12191
12192   /* bit variables done */
12193   /* general case */
12194   size = AOP_SIZE(result);
12195   offset = 0 ;
12196
12197   if(AOP_TYPE(right) == AOP_LIT) {
12198         if(!IS_FLOAT(operandType( right )))
12199                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12200         else {
12201            union {
12202               unsigned long lit_int;
12203               float lit_float;
12204             } info;
12205         
12206                 /* take care if literal is a float */
12207                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12208                 lit = info.lit_int;
12209         }
12210   }
12211
12212 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12213 //                      sizeof(unsigned long int), sizeof(float));
12214
12215
12216   if (AOP_TYPE(right) == AOP_REG) {
12217     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12218     while (size--) {
12219       
12220       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12221     } // while
12222     goto release;
12223   }
12224
12225   if(AOP_TYPE(right) != AOP_LIT
12226         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12227         && !IS_FUNC(OP_SYM_TYPE(right))
12228         ) {
12229         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12230         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12231
12232         // set up table pointer
12233         if(is_LitOp(right)) {
12234 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12235                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12236                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12237                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12238                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12239                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12240                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12241         } else {
12242 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12243                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12244                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12245                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12246                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12247                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12248                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12249         }
12250
12251         size = min(AOP_SIZE(right), AOP_SIZE(result));
12252         while(size--) {
12253                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12254                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12255                         pic16_popGet(AOP(result),offset)));
12256                 offset++;
12257         }
12258
12259         if(AOP_SIZE(result) > AOP_SIZE(right)) {
12260                 size = AOP_SIZE(result) - AOP_SIZE(right);
12261                 while(size--) {
12262                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12263                         offset++;
12264                 }
12265         }
12266         goto release;
12267   }
12268
12269
12270
12271 #if 0
12272 /* VR - What is this?! */
12273   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12274     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12275     if(aopIdx(AOP(result),0) == 4) {
12276
12277       /* this is a workaround to save value of right into wreg too,
12278        * value of wreg is going to be used later */
12279       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12280       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12281       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12282       goto release;
12283     } else
12284 //      assert(0);
12285       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12286   }
12287 #endif
12288
12289   know_W=-1;
12290   while (size--) {
12291   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12292     if(AOP_TYPE(right) == AOP_LIT) {
12293       if(lit&0xff) {
12294         if(know_W != (lit&0xff))
12295           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12296         know_W = lit&0xff;
12297         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12298       } else
12299         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12300
12301       lit >>= 8;
12302
12303     } else if (AOP_TYPE(right) == AOP_CRY) {
12304       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12305       if(offset == 0) {
12306         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12307         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12308         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12309       }
12310     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12311         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12312         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12313     } else {
12314       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12315
12316       if(!_G.resDirect)         /* use this aopForSym feature */
12317         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12318     }
12319             
12320     offset++;
12321   }
12322   
12323  release:
12324   pic16_freeAsmop (right,NULL,ic,FALSE);
12325   pic16_freeAsmop (result,NULL,ic,TRUE);
12326 }   
12327
12328 /*-----------------------------------------------------------------*/
12329 /* genJumpTab - generates code for jump table                       */
12330 /*-----------------------------------------------------------------*/
12331 static void genJumpTab (iCode *ic)
12332 {
12333   symbol *jtab;
12334   char *l;
12335   pCodeOp *jt_offs;
12336   pCodeOp *jt_offs_hi;
12337   pCodeOp *jt_label;
12338
12339     FENTRY;
12340
12341     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12342     /* get the condition into accumulator */
12343     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12344     MOVA(l);
12345     /* multiply by three */
12346     pic16_emitcode("add","a,acc");
12347     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12348
12349     jtab = newiTempLabel(NULL);
12350     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12351     pic16_emitcode("jmp","@a+dptr");
12352     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12353
12354 #if 0
12355     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12356     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12357     emitSKPNC;
12358     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12359     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12360     pic16_emitpLabel(jtab->key);
12361
12362 #else
12363
12364     jt_offs = pic16_popGetTempReg(0);
12365     jt_offs_hi = pic16_popGetTempReg(1);
12366     jt_label = pic16_popGetLabel (jtab->key);
12367     //fprintf (stderr, "Creating jump table...\n");
12368
12369     // calculate offset into jump table (idx * sizeof (GOTO))
12370     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12371     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12372     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12373     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12374     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12375     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12376     pic16_emitpcode(POC_MOVWF , jt_offs);
12377
12378     // prepare PCLATx (set to first entry in jump table)
12379     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12380     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12381     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12382     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12383     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12384
12385     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12386     pic16_emitpcode(POC_ADDWF , jt_offs);
12387     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12388     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12389     emitSKPNC;
12390     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12391
12392     // release temporaries and prepare jump into table (new PCL --> WREG)
12393     pic16_emitpcode(POC_MOVFW , jt_offs);
12394     pic16_popReleaseTempReg (jt_offs_hi, 1);
12395     pic16_popReleaseTempReg (jt_offs, 0);
12396
12397     // jump into the table
12398     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12399
12400     pic16_emitpLabelFORCE(jtab->key);
12401
12402 #endif
12403     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12404
12405     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12406     /* now generate the jump labels */
12407     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12408          jtab = setNextItem(IC_JTLABELS(ic))) {
12409 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12410         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12411         
12412     }
12413     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12414
12415 }
12416
12417 /*-----------------------------------------------------------------*/
12418 /* genMixedOperation - gen code for operators between mixed types  */
12419 /*-----------------------------------------------------------------*/
12420 /*
12421   TSD - Written for the PIC port - but this unfortunately is buggy.
12422   This routine is good in that it is able to efficiently promote 
12423   types to different (larger) sizes. Unfortunately, the temporary
12424   variables that are optimized out by this routine are sometimes
12425   used in other places. So until I know how to really parse the 
12426   iCode tree, I'm going to not be using this routine :(.
12427 */
12428 static int genMixedOperation (iCode *ic)
12429 {
12430 #if 0
12431   operand *result = IC_RESULT(ic);
12432   sym_link *ctype = operandType(IC_LEFT(ic));
12433   operand *right = IC_RIGHT(ic);
12434   int ret = 0;
12435   int big,small;
12436   int offset;
12437
12438   iCode *nextic;
12439   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12440
12441   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12442
12443   nextic = ic->next;
12444   if(!nextic)
12445     return 0;
12446
12447   nextright = IC_RIGHT(nextic);
12448   nextleft  = IC_LEFT(nextic);
12449   nextresult = IC_RESULT(nextic);
12450
12451   pic16_aopOp(right,ic,FALSE);
12452   pic16_aopOp(result,ic,FALSE);
12453   pic16_aopOp(nextright,  nextic, FALSE);
12454   pic16_aopOp(nextleft,   nextic, FALSE);
12455   pic16_aopOp(nextresult, nextic, FALSE);
12456
12457   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12458
12459     operand *t = right;
12460     right = nextright;
12461     nextright = t; 
12462
12463     pic16_emitcode(";remove right +","");
12464
12465   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12466 /*
12467     operand *t = right;
12468     right = nextleft;
12469     nextleft = t; 
12470 */
12471     pic16_emitcode(";remove left +","");
12472   } else
12473     return 0;
12474
12475   big = AOP_SIZE(nextleft);
12476   small = AOP_SIZE(nextright);
12477
12478   switch(nextic->op) {
12479
12480   case '+':
12481     pic16_emitcode(";optimize a +","");
12482     /* if unsigned or not an integral type */
12483     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12484       pic16_emitcode(";add a bit to something","");
12485     } else {
12486
12487       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12488
12489       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12490         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12491         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12492       } else
12493         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12494
12495       offset = 0;
12496       while(--big) {
12497
12498         offset++;
12499
12500         if(--small) {
12501           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12502             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12503             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12504           }
12505
12506           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12507           emitSKPNC;
12508           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12509                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12510                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12511           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12512           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12513
12514         } else {
12515           pic16_emitcode("rlf","known_zero,w");
12516
12517           /*
12518             if right is signed
12519               btfsc  right,7
12520                addlw ff
12521           */
12522           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12523             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12524             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12525           } else {
12526             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12527           }
12528         }
12529       }
12530       ret = 1;
12531     }
12532   }
12533   ret = 1;
12534
12535 release:
12536   pic16_freeAsmop(right,NULL,ic,TRUE);
12537   pic16_freeAsmop(result,NULL,ic,TRUE);
12538   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12539   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12540   if(ret)
12541     nextic->generated = 1;
12542
12543   return ret;
12544 #else
12545   return 0;
12546 #endif
12547 }
12548 /*-----------------------------------------------------------------*/
12549 /* genCast - gen code for casting                                  */
12550 /*-----------------------------------------------------------------*/
12551 static void genCast (iCode *ic)
12552 {
12553   operand *result = IC_RESULT(ic);
12554   sym_link *ctype = operandType(IC_LEFT(ic));
12555   sym_link *rtype = operandType(IC_RIGHT(ic));
12556   sym_link *restype = operandType(IC_RESULT(ic));
12557   operand *right = IC_RIGHT(ic);
12558   int size, offset ;
12559
12560
12561     FENTRY;
12562
12563         /* if they are equivalent then do nothing */
12564 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12565 //              return ;
12566
12567         pic16_aopOp(right,ic,FALSE) ;
12568         pic16_aopOp(result,ic,FALSE);
12569
12570         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12571
12572
12573         /* if the result is a bit */
12574         if (AOP_TYPE(result) == AOP_CRY) {
12575         
12576                 /* if the right size is a literal then
12577                  * we know what the value is */
12578                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12579
12580                 if (AOP_TYPE(right) == AOP_LIT) {
12581                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12582                                 pic16_popGet(AOP(result),0));
12583
12584                         if (((int) operandLitValue(right))) 
12585                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12586                                         AOP(result)->aopu.aop_dir,
12587                                         AOP(result)->aopu.aop_dir);
12588                         else
12589                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12590                                         AOP(result)->aopu.aop_dir,
12591                                         AOP(result)->aopu.aop_dir);
12592                         goto release;
12593                 }
12594
12595                 /* the right is also a bit variable */
12596                 if (AOP_TYPE(right) == AOP_CRY) {
12597                         emitCLRC;
12598                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12599
12600                         pic16_emitcode("clrc","");
12601                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12602                                 AOP(right)->aopu.aop_dir,
12603                                 AOP(right)->aopu.aop_dir);
12604                         pic16_aopPut(AOP(result),"c",0);
12605                         goto release ;
12606                 }
12607
12608                 /* we need to or */
12609                 if (AOP_TYPE(right) == AOP_REG) {
12610                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12611                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12612                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12613                 }
12614                 pic16_toBoolean(right);
12615                 pic16_aopPut(AOP(result),"a",0);
12616                 goto release ;
12617         }
12618
12619         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12620           int offset = 1;
12621
12622                 size = AOP_SIZE(result);
12623
12624                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12625
12626                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12627                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12628                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12629
12630                 while (size--)
12631                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12632
12633                 goto release;
12634         }
12635
12636         if(IS_BITFIELD(getSpec(restype))
12637           && IS_BITFIELD(getSpec(rtype))) {
12638           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12639         }
12640
12641         /* if they are the same size : or less */
12642         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12643
12644                 /* if they are in the same place */
12645                 if (pic16_sameRegs(AOP(right),AOP(result)))
12646                         goto release;
12647
12648                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12649 #if 0
12650                 if (IS_PTR_CONST(rtype))
12651 #else
12652                 if (IS_CODEPTR(rtype))
12653 #endif
12654                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12655
12656 #if 0
12657                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12658 #else
12659                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12660 #endif
12661                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12662
12663 #if 0
12664                 if(AOP_TYPE(right) == AOP_IMMD) {
12665                   pCodeOp *pcop0, *pcop1, *pcop2;
12666                   symbol *sym = OP_SYMBOL( right );
12667
12668                         size = AOP_SIZE(result);
12669                         /* low */
12670                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12671                         /* high */
12672                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12673                         /* upper */
12674                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12675         
12676                         if (size == 3) {
12677                                 pic16_emitpcode(POC_MOVLW, pcop0);
12678                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12679                                 pic16_emitpcode(POC_MOVLW, pcop1);
12680                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12681                                 pic16_emitpcode(POC_MOVLW, pcop2);
12682                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12683                         } else
12684                         if (size == 2) {
12685                                 pic16_emitpcode(POC_MOVLW, pcop0);
12686                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12687                                 pic16_emitpcode(POC_MOVLW, pcop1);
12688                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12689                         } else {
12690                                 pic16_emitpcode(POC_MOVLW, pcop0);
12691                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12692                         }
12693                 } else
12694 #endif
12695                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12696                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12697                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12698                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12699                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12700                         if(AOP_SIZE(result) <2)
12701                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12702                 } else {
12703                         /* if they in different places then copy */
12704                         size = AOP_SIZE(result);
12705                         offset = 0 ;
12706                         while (size--) {
12707                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12708                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12709                                 offset++;
12710                         }
12711                 }
12712                 goto release;
12713         }
12714
12715         /* if the result is of type pointer */
12716         if (IS_PTR(ctype)) {
12717           int p_type;
12718           sym_link *type = operandType(right);
12719           sym_link *etype = getSpec(type);
12720
12721                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
12722
12723                 /* pointer to generic pointer */
12724                 if (IS_GENPTR(ctype)) {
12725                   char *l = zero;
12726             
12727                         if (IS_PTR(type)) 
12728                                 p_type = DCL_TYPE(type);
12729                         else {
12730                 /* we have to go by the storage class */
12731                 p_type = PTR_TYPE(SPEC_OCLS(etype));
12732
12733 /*              if (SPEC_OCLS(etype)->codesp )  */
12734 /*                  p_type = CPOINTER ;  */
12735 /*              else */
12736 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12737 /*                      p_type = FPOINTER ; */
12738 /*                  else */
12739 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12740 /*                          p_type = PPOINTER; */
12741 /*                      else */
12742 /*                          if (SPEC_OCLS(etype) == idata ) */
12743 /*                              p_type = IPOINTER ; */
12744 /*                          else */
12745 /*                              p_type = POINTER ; */
12746             }
12747                 
12748             /* the first two bytes are known */
12749       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
12750             size = GPTRSIZE - 1; 
12751             offset = 0 ;
12752             while (size--) {
12753               if(offset < AOP_SIZE(right)) {
12754                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12755                 mov2f(AOP(result), AOP(right), offset);
12756 /*
12757                 if ((AOP_TYPE(right) == AOP_PCODE) && 
12758                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12759                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12760                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12761                 } else { 
12762                   
12763                   pic16_aopPut(AOP(result),
12764                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12765                          offset);
12766                 }
12767 */
12768               } else 
12769                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12770               offset++;
12771             }
12772             /* the last byte depending on type */
12773             switch (p_type) {
12774             case IPOINTER:
12775             case POINTER:
12776                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12777                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12778 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
12779                 break;
12780
12781             case CPOINTER:
12782                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12783                 break;
12784
12785             case FPOINTER:
12786               pic16_emitcode(";BUG!? ","%d",__LINE__);
12787                 l = one;
12788                 break;
12789             case PPOINTER:
12790               pic16_emitcode(";BUG!? ","%d",__LINE__);
12791                 l = "#0x03";
12792                 break;
12793
12794             case GPOINTER:
12795               pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12796               break;
12797               
12798             default:
12799                 /* this should never happen */
12800                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
12801                        "got unknown pointer type");
12802                 exit(1);
12803             }
12804             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
12805             goto release ;
12806         }
12807         
12808         /* just copy the pointers */
12809         size = AOP_SIZE(result);
12810         offset = 0 ;
12811         while (size--) {
12812             pic16_aopPut(AOP(result),
12813                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12814                    offset);
12815             offset++;
12816         }
12817         goto release ;
12818     }
12819     
12820
12821
12822     /* so we now know that the size of destination is greater
12823     than the size of the source.
12824     Now, if the next iCode is an operator then we might be
12825     able to optimize the operation without performing a cast.
12826     */
12827     if(genMixedOperation(ic))
12828       goto release;
12829
12830     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12831     
12832     /* we move to result for the size of source */
12833     size = AOP_SIZE(right);
12834     offset = 0 ;
12835     while (size--) {
12836       mov2f(AOP(result), AOP(right), offset);
12837       offset++;
12838     }
12839
12840     /* now depending on the sign of the destination */
12841     size = AOP_SIZE(result) - AOP_SIZE(right);
12842     /* if unsigned or not an integral type */
12843     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
12844       while (size--)
12845         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12846     } else {
12847       /* we need to extend the sign :( */
12848
12849       if(size == 1) {
12850         /* Save one instruction of casting char to int */
12851         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
12852         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12853         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
12854       } else {
12855         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
12856
12857         if(offset)
12858           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12859         else
12860           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12861         
12862         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
12863
12864         while (size--)
12865           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
12866       }
12867     }
12868
12869 release:
12870     pic16_freeAsmop(right,NULL,ic,TRUE);
12871     pic16_freeAsmop(result,NULL,ic,TRUE);
12872
12873 }
12874
12875 /*-----------------------------------------------------------------*/
12876 /* genDjnz - generate decrement & jump if not zero instrucion      */
12877 /*-----------------------------------------------------------------*/
12878 static int genDjnz (iCode *ic, iCode *ifx)
12879 {
12880     symbol *lbl, *lbl1;
12881     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12882
12883     if (!ifx)
12884         return 0;
12885     
12886     /* if the if condition has a false label
12887        then we cannot save */
12888     if (IC_FALSE(ifx))
12889         return 0;
12890
12891     /* if the minus is not of the form 
12892        a = a - 1 */
12893     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
12894         !IS_OP_LITERAL(IC_RIGHT(ic)))
12895         return 0;
12896
12897     if (operandLitValue(IC_RIGHT(ic)) != 1)
12898         return 0;
12899
12900     /* if the size of this greater than one then no
12901        saving */
12902     if (getSize(operandType(IC_RESULT(ic))) > 1)
12903         return 0;
12904
12905     /* otherwise we can save BIG */
12906     lbl = newiTempLabel(NULL);
12907     lbl1= newiTempLabel(NULL);
12908
12909     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
12910     
12911     if (IS_AOP_PREG(IC_RESULT(ic))) {
12912         pic16_emitcode("dec","%s",
12913                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12914         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12915         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
12916     } else {    
12917
12918
12919       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
12920       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
12921
12922       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12923       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
12924
12925     }
12926     
12927     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
12928     ifx->generated = 1;
12929     return 1;
12930 }
12931
12932 /*-----------------------------------------------------------------*/
12933 /* genReceive - generate code for a receive iCode                  */
12934 /*-----------------------------------------------------------------*/
12935 static void genReceive (iCode *ic)
12936 {    
12937
12938   FENTRY;
12939
12940 #if 0
12941   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
12942         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
12943 #endif
12944 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
12945
12946   if (isOperandInFarSpace(IC_RESULT(ic))
12947       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
12948           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
12949
12950     int size = getSize(operandType(IC_RESULT(ic)));
12951     int offset =  pic16_fReturnSizePic - size;
12952
12953       assert( 0 );
12954       while (size--) {
12955         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
12956                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
12957                       offset++;
12958         }
12959
12960       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
12961
12962       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
12963       size = AOP_SIZE(IC_RESULT(ic));
12964       offset = 0;
12965       while (size--) {
12966         pic16_emitcode ("pop","acc");
12967         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
12968       }
12969   } else {
12970     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
12971     _G.accInUse++;
12972     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
12973     _G.accInUse--;
12974
12975     /* set pseudo stack pointer to where it should be - dw*/
12976     GpsuedoStkPtr = ic->parmBytes;
12977
12978     /* setting GpsuedoStkPtr has side effects here: */
12979     assignResultValue(IC_RESULT(ic), 0);
12980   }
12981
12982   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
12983 }
12984
12985 /*-----------------------------------------------------------------*/
12986 /* genDummyRead - generate code for dummy read of volatiles        */
12987 /*-----------------------------------------------------------------*/
12988 static void
12989 genDummyRead (iCode * ic)
12990 {
12991   pic16_emitcode ("; genDummyRead","");
12992   pic16_emitcode ("; not implemented","");
12993
12994   ic = ic;
12995 }
12996
12997 /*-----------------------------------------------------------------*/
12998 /* genpic16Code - generate code for pic16 based controllers        */
12999 /*-----------------------------------------------------------------*/
13000 /*
13001  * At this point, ralloc.c has gone through the iCode and attempted
13002  * to optimize in a way suitable for a PIC. Now we've got to generate
13003  * PIC instructions that correspond to the iCode.
13004  *
13005  * Once the instructions are generated, we'll pass through both the
13006  * peep hole optimizer and the pCode optimizer.
13007  *-----------------------------------------------------------------*/
13008
13009 void genpic16Code (iCode *lic)
13010 {
13011   iCode *ic;
13012   int cln = 0;
13013
13014     lineHead = lineCurr = NULL;
13015
13016     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13017     pic16_addpBlock(pb);
13018
13019 #if 0
13020     /* if debug information required */
13021     if (options.debug && currFunc) {
13022       if (currFunc) {
13023         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13024       }
13025     }
13026 #endif
13027
13028     for (ic = lic ; ic ; ic = ic->next ) {
13029
13030       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
13031       if ( cln != ic->lineno ) {
13032         if ( options.debug ) {
13033           debugFile->writeCLine (ic);
13034         }
13035         
13036         if(!options.noCcodeInAsm) {
13037           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13038               printCLine(ic->filename, ic->lineno)));
13039         }
13040
13041         cln = ic->lineno ;
13042       }
13043         
13044       if(options.iCodeInAsm) {
13045         char *l;
13046
13047           /* insert here code to print iCode as comment */
13048           l = Safe_strdup(printILine(ic));
13049           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13050       }
13051         
13052       /* if the result is marked as
13053        * spilt and rematerializable or code for
13054        * this has already been generated then
13055        * do nothing */
13056       if (resultRemat(ic) || ic->generated ) 
13057         continue ;
13058         
13059       /* depending on the operation */
13060       switch (ic->op) {
13061         case '!' :
13062           pic16_genNot(ic);
13063           break;
13064             
13065         case '~' :
13066           pic16_genCpl(ic);
13067           break;
13068             
13069         case UNARYMINUS:
13070           genUminus (ic);
13071           break;
13072             
13073         case IPUSH:
13074           genIpush (ic);
13075           break;
13076             
13077         case IPOP:
13078           /* IPOP happens only when trying to restore a 
13079            * spilt live range, if there is an ifx statement
13080            * following this pop then the if statement might
13081            * be using some of the registers being popped which
13082            * would destroy the contents of the register so
13083            * we need to check for this condition and handle it */
13084            if (ic->next
13085              && ic->next->op == IFX
13086              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13087                genIfx (ic->next,ic);
13088           else
13089             genIpop (ic);
13090           break; 
13091             
13092         case CALL:
13093           genCall (ic);
13094           break;
13095             
13096         case PCALL:
13097           genPcall (ic);
13098           break;
13099             
13100         case FUNCTION:
13101           genFunction (ic);
13102           break;
13103             
13104         case ENDFUNCTION:
13105           genEndFunction (ic);
13106           break;
13107             
13108         case RETURN:
13109           genRet (ic);
13110           break;
13111             
13112         case LABEL:
13113           genLabel (ic);
13114           break;
13115             
13116         case GOTO:
13117           genGoto (ic);
13118           break;
13119             
13120         case '+' :
13121           pic16_genPlus (ic) ;
13122           break;
13123             
13124         case '-' :
13125           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13126             pic16_genMinus (ic);
13127           break;
13128
13129         case '*' :
13130           genMult (ic);
13131           break;
13132             
13133         case '/' :
13134           genDiv (ic) ;
13135           break;
13136             
13137         case '%' :
13138           genMod (ic);
13139           break;
13140             
13141         case '>' :
13142           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13143           break;
13144             
13145         case '<' :
13146           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13147           break;
13148             
13149         case LE_OP:
13150         case GE_OP:
13151         case NE_OP:
13152           /* note these two are xlated by algebraic equivalence
13153            * during parsing SDCC.y */
13154           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13155             "got '>=' or '<=' shouldn't have come here");
13156           break;
13157
13158         case EQ_OP:
13159           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13160           break;            
13161             
13162         case AND_OP:
13163           genAndOp (ic);
13164           break;
13165             
13166         case OR_OP:
13167           genOrOp (ic);
13168           break;
13169             
13170         case '^' :
13171           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13172           break;
13173             
13174         case '|' :
13175           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13176           break;
13177             
13178         case BITWISEAND:
13179           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13180           break;
13181             
13182         case INLINEASM:
13183           genInline (ic);
13184           break;
13185             
13186         case RRC:
13187           genRRC (ic);
13188           break;
13189             
13190         case RLC:
13191           genRLC (ic);
13192           break;
13193             
13194         case GETHBIT:
13195           genGetHbit (ic);
13196           break;
13197             
13198         case LEFT_OP:
13199           genLeftShift (ic);
13200           break;
13201             
13202         case RIGHT_OP:
13203           genRightShift (ic);
13204           break;
13205             
13206         case GET_VALUE_AT_ADDRESS:
13207           genPointerGet(ic);
13208           break;
13209             
13210         case '=' :
13211           if (POINTER_SET(ic))
13212             genPointerSet(ic);
13213           else
13214             genAssign(ic);
13215           break;
13216             
13217         case IFX:
13218           genIfx (ic,NULL);
13219           break;
13220             
13221         case ADDRESS_OF:
13222           genAddrOf (ic);
13223           break;
13224             
13225         case JUMPTABLE:
13226           genJumpTab (ic);
13227           break;
13228             
13229         case CAST:
13230           genCast (ic);
13231           break;
13232             
13233         case RECEIVE:
13234           genReceive(ic);
13235           break;
13236             
13237         case SEND:
13238           addSet(&_G.sendSet,ic);
13239           break;
13240
13241         case DUMMY_READ_VOLATILE:
13242           genDummyRead (ic);
13243           break;
13244
13245         default :
13246           ic = ic;
13247       }
13248     }
13249
13250
13251     /* now we are ready to call the
13252        peep hole optimizer */
13253     if (!options.nopeep)
13254       peepHole (&lineHead);
13255
13256     /* now do the actual printing */
13257     printLine (lineHead, codeOutFile);
13258
13259 #ifdef PCODE_DEBUG
13260     DFPRINTF((stderr,"printing pBlock\n\n"));
13261     pic16_printpBlock(stdout,pb);
13262 #endif
13263
13264     return;
13265 }
13266