* src/pic16/gen.c (genGenericShift) added handling of differently
[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 /* Set the following to 1 to enable the slower/bigger
51  * but more robust generic shifting routine (which also
52  * operates correctly with negative shift values). */
53 #define USE_GENERIC_SIGNED_SHIFT 1
54
55 /* Set the following to 1 to enable the new
56  * stripped down genCmp version.
57  * This version should be easier to understand,
58  * more reliable and (sigh) slighly slower. */
59 #define USE_SIMPLE_GENCMP 1
60
61 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
62 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
63 void pic16_genMult8X8_8 (operand *, operand *,operand *);
64 void pic16_genMult16X16_16(operand *, operand *, operand *);
65 void pic16_genMult32X32_32(operand *, operand *, operand *);
66 pCode *pic16_AssembleLine(char *line, int peeps);
67 extern void pic16_printpBlock(FILE *of, pBlock *pb);
68 static asmop *newAsmop (short type);
69 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
70 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
71 static void mov2f(asmop *dst, asmop *src, int offset);
72 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
73 static pCodeOp *pic16_popRegFromIdx(int rIdx);
74
75 //static int aopIdx (asmop *aop, int offset);
76
77 int pic16_labelOffset=0;
78 extern int pic16_debug_verbose;
79 #if !(USE_GENERIC_SIGNED_SHIFT)
80 static int optimized_for_speed = 0;
81 #endif
82 /*
83   hack hack
84
85 */
86
87 extern set *externs;
88
89 /* max_key keeps track of the largest label number used in 
90    a function. This is then used to adjust the label offset
91    for the next function.
92 */
93 static int max_key=0;
94 static int GpsuedoStkPtr=0;
95
96 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
97
98 unsigned int pic16aopLiteral (value *val, int offset);
99 const char *pic16_AopType(short type);
100 static iCode *ifxForOp ( operand *op, iCode *ic );
101
102 void pic16_pushpCodeOp(pCodeOp *pcop);
103 void pic16_poppCodeOp(pCodeOp *pcop);
104
105 static bool is_LitOp(operand *op);
106 static bool is_LitAOp(asmop *aop);
107
108
109 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
110
111 /* set the following macro to 1 to enable passing the
112  * first byte of functions parameters via WREG */
113 #define USE_WREG_IN_FUNC_PARAMS 0
114
115
116 /* this is the down and dirty file with all kinds of 
117    kludgy & hacky stuff. This is what it is all about
118    CODE GENERATION for a specific MCU . some of the
119    routines may be reusable, will have to see */
120
121 static char *zero = "#0x00";
122 static char *one  = "#0x01";
123 //static char *spname = "sp";
124
125
126 /*
127  * Function return value policy (MSB-->LSB):
128  *  8 bits      -> WREG
129  * 16 bits      -> PRODL:WREG
130  * 24 bits      -> PRODH:PRODL:WREG
131  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
132  * >32 bits     -> on stack, and FSR0 points to the beginning
133  *
134  */
135  
136
137 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
138 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
139 static char **fReturn = fReturnpic16;
140
141 static char *accUse[] = {"WREG"};
142
143 //static short rbank = -1;
144
145 static struct {
146     short r0Pushed;
147     short r1Pushed;
148     short fsr0Pushed;
149     short accInUse;
150     short inLine;
151     short debugLine;
152     short nRegsSaved;
153     short ipushRegs;
154     set *sendSet;
155     set *stackRegSet;
156     int interruptvector;
157     int usefastretfie;
158     bitVect *fregsUsed;
159     int stack_lat;                      /* stack offset latency */
160     int resDirect;
161     int useWreg;                        /* flag when WREG is used to pass function parameter */
162 } _G;
163
164 /* Resolved ifx structure. This structure stores information
165    about an iCode ifx that makes it easier to generate code.
166 */
167 typedef struct resolvedIfx {
168   symbol *lbl;     /* pointer to a label */
169   int condition;   /* true or false ifx */
170   int generated;   /* set true when the code associated with the ifx
171                     * is generated */
172 } resolvedIfx;
173
174 extern int pic16_ptrRegReq ;
175 extern int pic16_nRegs;
176 extern FILE *codeOutFile;
177 //static void saverbank (int, iCode *,bool);
178
179 static lineNode *lineHead = NULL;
180 static lineNode *lineCurr = NULL;
181
182 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
183 0xE0, 0xC0, 0x80, 0x00};
184 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
185 0x07, 0x03, 0x01, 0x00};
186
187 static  pBlock *pb;
188
189 /*-----------------------------------------------------------------*/
190 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
191 /*                 exponent of 2 is returned, otherwise -1 is      */
192 /*                 returned.                                       */
193 /* note that this is similar to the function `powof2' in SDCCsymt  */
194 /* if(n == 2^y)                                                    */
195 /*   return y;                                                     */
196 /* return -1;                                                      */
197 /*-----------------------------------------------------------------*/
198 int pic16_my_powof2 (unsigned long num)
199 {
200   if(num) {
201     if( (num & (num-1)) == 0) {
202       int nshifts = -1;
203       while(num) {
204         num>>=1;
205         nshifts++;
206       }
207       return nshifts;
208     }
209   }
210
211   return -1;
212 }
213
214 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
215 {
216   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
217                        line_no,
218                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
219                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
220                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
221                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
222                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
223                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
224                        ((result) ? AOP_SIZE(result) : 0));
225 }
226
227 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
228 {
229
230   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
231                        line_no,
232                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
233                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
234                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
235                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
236                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
237                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
238
239 }
240
241 void pic16_emitpcomment (char *fmt, ...)
242 {
243     va_list ap;
244     char lb[INITIAL_INLINEASM];  
245     char *lbp = lb;
246
247     va_start(ap,fmt);   
248
249     lb[0] = ';';
250     vsprintf(lb+1,fmt,ap);
251
252     while (isspace(*lbp)) lbp++;
253
254     if (lbp && *lbp) 
255         lineCurr = (lineCurr ?
256                     connectLine(lineCurr,newLineNode(lb)) :
257                     (lineHead = newLineNode(lb)));
258     lineCurr->isInline = _G.inLine;
259     lineCurr->isDebug  = _G.debugLine;
260
261     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
262     va_end(ap);
263
264 //      fprintf(stderr, "%s\n", lb);
265 }
266
267 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
268 {
269     va_list ap;
270     char lb[INITIAL_INLINEASM];  
271     char *lbp = lb;
272
273     if(!pic16_debug_verbose)
274       return;
275
276     va_start(ap,fmt);   
277
278     if (inst && *inst) {
279         if (fmt && *fmt)
280             sprintf(lb,"%s\t",inst);
281         else
282             sprintf(lb,"%s",inst);
283         vsprintf(lb+(strlen(lb)),fmt,ap);
284     }  else
285         vsprintf(lb,fmt,ap);
286
287     while (isspace(*lbp)) lbp++;
288
289     if (lbp && *lbp) 
290         lineCurr = (lineCurr ?
291                     connectLine(lineCurr,newLineNode(lb)) :
292                     (lineHead = newLineNode(lb)));
293     lineCurr->isInline = _G.inLine;
294     lineCurr->isDebug  = _G.debugLine;
295
296     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
297     va_end(ap);
298
299 //      fprintf(stderr, "%s\n", lb);
300 }
301
302
303
304 void pic16_emitpLabel(int key)
305 {
306   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
307 }
308
309 void pic16_emitpLabelFORCE(int key)
310 {
311   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
312 }
313
314 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
315 {
316
317   if(pcop)
318     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
319   else
320     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
321 }
322
323 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
324 {
325   if(pcop)
326     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
327   else
328     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
329 }
330   
331 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
332 {
333
334   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
335
336 }
337
338
339 #if 1
340 #define pic16_emitcode  DEBUGpic16_emitcode
341 #else
342 /*-----------------------------------------------------------------*/
343 /* pic16_emitcode - writes the code into a file : for now it is simple    */
344 /*-----------------------------------------------------------------*/
345 void pic16_emitcode (char *inst,char *fmt, ...)
346 {
347     va_list ap;
348     char lb[INITIAL_INLINEASM];  
349     char *lbp = lb;
350
351     va_start(ap,fmt);   
352
353     if (inst && *inst) {
354         if (fmt && *fmt)
355             sprintf(lb,"%s\t",inst);
356         else
357             sprintf(lb,"%s",inst);
358         vsprintf(lb+(strlen(lb)),fmt,ap);
359     }  else
360         vsprintf(lb,fmt,ap);
361
362     while (isspace(*lbp)) lbp++;
363
364     if (lbp && *lbp) 
365         lineCurr = (lineCurr ?
366                     connectLine(lineCurr,newLineNode(lb)) :
367                     (lineHead = newLineNode(lb)));
368     lineCurr->isInline = _G.inLine;
369     lineCurr->isDebug  = _G.debugLine;
370
371 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
372
373 //    if(pic16_debug_verbose)
374 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
375
376     va_end(ap);
377 }
378 #endif
379
380
381 /*-----------------------------------------------------------------*/
382 /* pic16_emitDebuggerSymbol - associate the current code location  */
383 /*   with a debugger symbol                                        */
384 /*-----------------------------------------------------------------*/
385 void
386 pic16_emitDebuggerSymbol (char * debugSym)
387 {
388   _G.debugLine = 1;
389   pic16_emitcode (";", "%s ==.", debugSym);
390   _G.debugLine = 0;
391 }
392
393
394 /*-----------------------------------------------------------------*/
395 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
396 /*-----------------------------------------------------------------*/
397 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
398 {
399 //    bool r0iu = FALSE , r1iu = FALSE;
400 //    bool r0ou = FALSE , r1ou = FALSE;
401     bool fsr0iu = FALSE, fsr0ou;
402     bool fsr2iu = FALSE, fsr2ou;
403     
404     fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
405
406     
407     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
408     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
409     
410     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
411     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
412
413     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
414         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
415         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
416     }
417
418     if(!fsr0iu && !fsr0ou) {
419         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
420         (*aopp)->type = AOP_FSR0;
421
422         fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
423         
424       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
425     }
426
427 #if 0
428     /* no usage of FSR2 */
429     if(!fsr2iu && !fsr2ou) {
430         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
431         (*aopp)->type = AOP_FSR2;
432
433       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
434     }
435 #endif
436         
437     /* now we know they both have usage */
438     /* if fsr0 not used in this instruction */
439     if (!fsr0iu) {
440         if (!_G.fsr0Pushed) {
441                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
442                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
443                 _G.fsr0Pushed++;
444         }
445
446         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
447         (*aopp)->type = AOP_FSR0;
448
449 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
450
451       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
452     }
453         
454
455     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
456     assert( 0 );
457
458     return NULL;
459 #if 0
460     /* the logic: if r0 & r1 used in the instruction
461     then we are in trouble otherwise */
462
463     /* first check if r0 & r1 are used by this
464     instruction, in which case we are in trouble */
465     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
466         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
467     {
468         goto endOfWorld;      
469     }
470
471     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
472     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
473
474     /* if no usage of r0 then return it */
475     if (!r0iu && !r0ou) {
476         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
477         (*aopp)->type = AOP_R0; 
478         
479         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
480     }
481
482     /* if no usage of r1 then return it */
483     if (!r1iu && !r1ou) {
484         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
485         (*aopp)->type = AOP_R1;
486
487         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
488     }    
489
490     /* now we know they both have usage */
491     /* if r0 not used in this instruction */
492     if (!r0iu) {
493         /* push it if not already pushed */
494         if (!_G.r0Pushed) {
495           //pic16_emitcode ("push","%s",
496           //          pic16_regWithIdx(R0_IDX)->dname);
497             _G.r0Pushed++ ;
498         }
499         
500         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
501         (*aopp)->type = AOP_R0;
502
503         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
504     }
505
506     /* if r1 not used then */
507
508     if (!r1iu) {
509         /* push it if not already pushed */
510         if (!_G.r1Pushed) {
511           //pic16_emitcode ("push","%s",
512           //          pic16_regWithIdx(R1_IDX)->dname);
513             _G.r1Pushed++ ;
514         }
515         
516         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
517         (*aopp)->type = AOP_R1;
518         return pic16_regWithIdx(R1_IDX);
519     }
520
521 endOfWorld :
522     /* I said end of world but not quite end of world yet */
523     /* if this is a result then we can push it on the stack*/
524     if (result) {
525         (*aopp)->type = AOP_STK;    
526         return NULL;
527     }
528
529     /* other wise this is true end of the world */
530     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
531            "getFreePtr should never reach here");
532     exit(0);
533 #endif
534 }
535
536 /*-----------------------------------------------------------------*/
537 /* newAsmop - creates a new asmOp                                  */
538 /*-----------------------------------------------------------------*/
539 static asmop *newAsmop (short type)
540 {
541     asmop *aop;
542
543     aop = Safe_calloc(1,sizeof(asmop));
544     aop->type = type;
545     return aop;
546 }
547
548 static void genSetDPTR(int n)
549 {
550     if (!n)
551     {
552         pic16_emitcode(";", "Select standard DPTR");
553         pic16_emitcode("mov", "dps, #0x00");
554     }
555     else
556     {
557         pic16_emitcode(";", "Select alternate DPTR");
558         pic16_emitcode("mov", "dps, #0x01");
559     }
560 }
561
562 /*-----------------------------------------------------------------*/
563 /* resolveIfx - converts an iCode ifx into a form more useful for  */
564 /*              generating code                                    */
565 /*-----------------------------------------------------------------*/
566 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
567 {
568   FENTRY2;
569   
570 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
571
572   if(!resIfx) 
573     return;
574
575
576   resIfx->condition = 1;    /* assume that the ifx is true */
577   resIfx->generated = 0;    /* indicate that the ifx has not been used */
578
579   if(!ifx) {
580     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
581
582 #if 1
583     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
584                         __FUNCTION__,__LINE__,resIfx->lbl->key);
585 #endif
586
587   } else {
588     if(IC_TRUE(ifx)) {
589       resIfx->lbl = IC_TRUE(ifx);
590     } else {
591       resIfx->lbl = IC_FALSE(ifx);
592       resIfx->condition = 0;
593     }
594
595 #if 1
596     if(IC_TRUE(ifx)) 
597       DEBUGpic16_emitcode("; +++","ifx true is non-null");
598     else
599       DEBUGpic16_emitcode("; +++","ifx true is null");
600     if(IC_FALSE(ifx)) 
601       DEBUGpic16_emitcode("; +++","ifx false is non-null");
602     else
603       DEBUGpic16_emitcode("; +++","ifx false is null");
604 #endif
605   }
606
607   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
608
609 }
610 #if 0
611 /*-----------------------------------------------------------------*/
612 /* pointerCode - returns the code for a pointer type               */
613 /*-----------------------------------------------------------------*/
614 static int pointerCode (sym_link *etype)
615 {
616
617     return PTR_TYPE(SPEC_OCLS(etype));
618
619 }
620 #endif
621
622 /*-----------------------------------------------------------------*/
623 /* aopForSym - for a true symbol                                   */
624 /*-----------------------------------------------------------------*/
625 static asmop *aopForSym (iCode *ic, operand *op, bool result)
626 {
627     symbol *sym=OP_SYMBOL(op);
628     asmop *aop;
629     memmap *space= SPEC_OCLS(sym->etype);
630
631     FENTRY2;
632     
633     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
634     
635 //    sym = OP_SYMBOL(op);
636
637     /* if already has one */
638     if (sym->aop) {
639             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
640         return sym->aop;
641     }
642
643 #if 0
644     /* if symbol was initially placed onStack then we must re-place it
645      * to direct memory, since pic16 does not have a specific stack */
646     if(sym->onStack) {
647         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
648     }
649 #endif
650
651 #if 1
652     /* assign depending on the storage class */
653     /* if it is on the stack or indirectly addressable */
654     /* space we need to assign either r0 or r1 to it   */    
655     if (sym->onStack || sym->iaccess) {
656       pCodeOp *pcop[4];
657       int i;
658       
659         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
660                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
661         
662         /* acquire a temporary register -- it is saved in function */
663
664         sym->aop = aop = newAsmop(AOP_STA);
665         aop->aopu.stk.stk = sym->stack;
666         aop->size = getSize(sym->type);
667
668
669         DEBUGpic16_emitcode("; +++", "%s:%d", __FILE__, __LINE__);
670         if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
671           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) {
672           pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
673           
674           for(i=0;i<aop->size;i++)
675             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
676             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
677         } else
678           for(i=0;i<aop->size;i++) {
679             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond( _G.fregsUsed, 0 );
680             _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx);
681           }
682
683
684 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
685
686 #if 1
687         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
688         
689         if(_G.accInUse) {
690                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
691         }
692         
693         for(i=0;i<aop->size;i++) {
694
695           /* initialise for stack access via frame pointer */
696           // operands on stack are accessible via "FSR2 + index" with index
697           // starting at 2 for arguments and growing from 0 downwards for
698           // local variables (index == 0 is not assigned so we add one here)
699           {
700             int soffs = sym->stack;
701             if (soffs <= 0) {
702               assert (soffs < 0);
703               soffs++;
704             } // if
705             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
706             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
707                             pic16_popCopyReg(&pic16_pc_plusw2), pcop[i]));
708           }
709         }
710         
711         if(_G.accInUse) {
712                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
713         }
714         
715         return (aop);
716 #endif
717
718 #if 0
719         /* now assign the address of the variable to 
720         the pointer register */
721         if (aop->type != AOP_STK) {
722
723             if (sym->onStack) {
724                     if ( _G.accInUse )
725                         pic16_emitcode("push","acc");
726
727                     pic16_emitcode("mov","a,_bp");
728                     pic16_emitcode("add","a,#0x%02x",
729                              ((sym->stack < 0) ?
730                               ((char)(sym->stack - _G.nRegsSaved )) :
731                               ((char)sym->stack)) & 0xff);
732                     pic16_emitcode("mov","%s,a",
733                              aop->aopu.aop_ptr->name);
734
735                     if ( _G.accInUse )
736                         pic16_emitcode("pop","acc");
737             } else
738                 pic16_emitcode("mov","%s,#%s",
739                          aop->aopu.aop_ptr->name,
740                          sym->rname);
741             aop->paged = space->paged;
742         } else
743             aop->aopu.aop_stk = sym->stack;
744         return aop;
745 #endif
746
747     }
748 #endif
749
750 #if 0
751     if (sym->onStack && options.stack10bit)
752     {
753         /* It's on the 10 bit stack, which is located in
754          * far data space.
755          */
756          
757       //DEBUGpic16_emitcode(";","%d",__LINE__);
758
759         if ( _G.accInUse )
760                 pic16_emitcode("push","acc");
761
762         pic16_emitcode("mov","a,_bp");
763         pic16_emitcode("add","a,#0x%02x",
764                  ((sym->stack < 0) ?
765                    ((char)(sym->stack - _G.nRegsSaved )) :
766                    ((char)sym->stack)) & 0xff);
767         
768         genSetDPTR(1);
769         pic16_emitcode ("mov","dpx1,#0x40");
770         pic16_emitcode ("mov","dph1,#0x00");
771         pic16_emitcode ("mov","dpl1, a");
772         genSetDPTR(0);
773         
774         if ( _G.accInUse )
775             pic16_emitcode("pop","acc");
776             
777         sym->aop = aop = newAsmop(AOP_DPTR2);
778         aop->size = getSize(sym->type); 
779         return aop;
780     }
781 #endif
782
783 #if 0
784     /* special case for a function */
785     if (IS_FUNC(sym->type)) {   
786         sym->aop = aop = newAsmop(AOP_PCODE);
787         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
788         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
789         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
790         PCOI(aop->aopu.pcop)->index = 0;
791         aop->size = FPTRSIZE; 
792         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
793         return aop;
794     }
795 #endif
796
797
798
799     //DEBUGpic16_emitcode(";","%d",__LINE__);
800     /* if in bit space */
801     if (IN_BITSPACE(space)) {
802         sym->aop = aop = newAsmop (AOP_CRY);
803         aop->aopu.aop_dir = sym->rname ;
804         aop->size = getSize(sym->type);
805         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
806         return aop;
807     }
808     /* if it is in direct space */
809     if (IN_DIRSPACE(space)) {
810         sym->aop = aop = newAsmop (AOP_DIR);
811         aop->aopu.aop_dir = sym->rname ;
812         aop->size = getSize(sym->type);
813         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
814         pic16_allocDirReg( IC_LEFT(ic) );
815         return aop;
816     }
817
818
819     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
820         sym->aop = aop = newAsmop (AOP_DIR);
821         aop->aopu.aop_dir = sym->rname ;
822         aop->size = getSize(sym->type);
823         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
824         pic16_allocDirReg( IC_LEFT(ic) );
825         return aop;
826     }
827
828
829     /* only remaining is far space */
830     sym->aop = aop = newAsmop(AOP_PCODE);
831
832 /* change the next if to 1 to revert to good old immediate code */
833         if(IN_CODESPACE(space)) {
834                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
835                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
836                 PCOI(aop->aopu.pcop)->index = 0;
837         } else {
838                 /* try to allocate via direct register */
839                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
840 //              aop->size = getSize( sym->type );
841         }
842
843         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
844                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
845
846 #if 0
847         if(!pic16_allocDirReg (IC_LEFT(ic)))
848                 return NULL;
849 #endif
850
851         if(IN_DIRSPACE( space ))
852                 aop->size = PTRSIZE;
853         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
854                 aop->size = FPTRSIZE;
855         else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
856         else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
857         else if(sym->onStack) {
858                 aop->size = PTRSIZE;
859         } else {
860                 assert( 0 );
861         }
862
863     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
864
865     /* if it is in code space */
866     if (IN_CODESPACE(space))
867         aop->code = 1;
868
869     return aop;     
870 }
871
872 /*-----------------------------------------------------------------*/
873 /* aopForRemat - rematerialzes an object                           */
874 /*-----------------------------------------------------------------*/
875 static asmop *aopForRemat (operand *op) // x symbol *sym)
876 {
877   symbol *sym = OP_SYMBOL(op);
878   operand *refop;
879   iCode *ic = NULL, *oldic;
880   asmop *aop = newAsmop(AOP_PCODE);
881   int val = 0;
882   int offset = 0;
883   int viaimmd=0;
884
885     FENTRY2;
886     
887         ic = sym->rematiCode;
888
889         if(IS_OP_POINTER(op)) {
890                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
891         }
892
893         for (;;) {
894                 oldic = ic;
895
896 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
897         
898                 if (ic->op == '+') {
899                         val += (int) operandLitValue(IC_RIGHT(ic));
900                 } else if (ic->op == '-') {
901                         val -= (int) operandLitValue(IC_RIGHT(ic));
902                 } else
903                         break;
904                 
905                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
906         }
907
908         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
909         refop = IC_LEFT(ic);
910
911         if(!op->isaddr)viaimmd++; else viaimmd=0;
912                 
913 /* set the following if to 1 to revert to good old immediate code */
914         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
915                 || viaimmd) {
916
917                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
918
919                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
920
921 #if 0
922                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
923 #else
924                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
925 #endif
926
927                 PCOI(aop->aopu.pcop)->index = val;
928                 
929                 aop->size = getSize( sym->type );
930         } else {
931                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
932
933                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
934                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
935
936                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
937         }
938
939
940         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
941                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
942 #if 0
943                 val, IS_PTR_CONST(operandType(op)));
944 #else
945                 val, IS_CODEPTR(operandType(op)));
946 #endif
947
948 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
949
950         pic16_allocDirReg (IC_LEFT(ic));
951
952         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
953                 aop->code = 1;
954
955   return aop;        
956 }
957
958 #if 0
959 static int aopIdx (asmop *aop, int offset)
960 {
961   if(!aop)
962     return -1;
963
964   if(aop->type !=  AOP_REG)
965     return -2;
966         
967   return aop->aopu.aop_reg[offset]->rIdx;
968
969 }
970 #endif
971
972 /*-----------------------------------------------------------------*/
973 /* regsInCommon - two operands have some registers in common       */
974 /*-----------------------------------------------------------------*/
975 static bool regsInCommon (operand *op1, operand *op2)
976 {
977     symbol *sym1, *sym2;
978     int i;
979
980     /* if they have registers in common */
981     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
982         return FALSE ;
983
984     sym1 = OP_SYMBOL(op1);
985     sym2 = OP_SYMBOL(op2);
986
987     if (sym1->nRegs == 0 || sym2->nRegs == 0)
988         return FALSE ;
989
990     for (i = 0 ; i < sym1->nRegs ; i++) {
991         int j;
992         if (!sym1->regs[i])
993             continue ;
994
995         for (j = 0 ; j < sym2->nRegs ;j++ ) {
996             if (!sym2->regs[j])
997                 continue ;
998
999             if (sym2->regs[j] == sym1->regs[i])
1000                 return TRUE ;
1001         }
1002     }
1003
1004     return FALSE ;
1005 }
1006
1007 /*-----------------------------------------------------------------*/
1008 /* operandsEqu - equivalent                                        */
1009 /*-----------------------------------------------------------------*/
1010 static bool operandsEqu ( operand *op1, operand *op2)
1011 {
1012     symbol *sym1, *sym2;
1013
1014     /* if they not symbols */
1015     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1016         return FALSE;
1017
1018     sym1 = OP_SYMBOL(op1);
1019     sym2 = OP_SYMBOL(op2);
1020
1021     /* if both are itemps & one is spilt
1022        and the other is not then false */
1023     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1024         sym1->isspilt != sym2->isspilt )
1025         return FALSE ;
1026
1027     /* if they are the same */
1028     if (sym1 == sym2)
1029         return TRUE ;
1030
1031     if (sym1->rname[0] && sym2->rname[0]
1032         && strcmp (sym1->rname, sym2->rname) == 0)
1033         return TRUE;
1034
1035
1036     /* if left is a tmp & right is not */
1037     if (IS_ITEMP(op1)  && 
1038         !IS_ITEMP(op2) &&
1039         sym1->isspilt  &&
1040         (sym1->usl.spillLoc == sym2))
1041         return TRUE;
1042
1043     if (IS_ITEMP(op2)  && 
1044         !IS_ITEMP(op1) &&
1045         sym2->isspilt  &&
1046         sym1->level > 0 &&
1047         (sym2->usl.spillLoc == sym1))
1048         return TRUE ;
1049
1050     return FALSE ;
1051 }
1052
1053 /*-----------------------------------------------------------------*/
1054 /* pic16_sameRegs - two asmops have the same registers                   */
1055 /*-----------------------------------------------------------------*/
1056 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1057 {
1058     int i;
1059
1060     if (aop1 == aop2)
1061         return TRUE ;
1062
1063     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1064                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1065
1066     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1067
1068     if (aop1->type != AOP_REG ||
1069         aop2->type != AOP_REG )
1070         return FALSE ;
1071
1072     if (aop1->size != aop2->size )
1073         return FALSE ;
1074
1075     for (i = 0 ; i < aop1->size ; i++ ) {
1076 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1077
1078 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1079         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1080             return FALSE ;
1081     }
1082
1083     return TRUE ;
1084 }
1085
1086 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1087 {
1088     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1089                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1090
1091     if(aop1 == aop2)return TRUE;
1092     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1093       
1094       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1095     
1096   return TRUE;
1097 }
1098
1099
1100 /*-----------------------------------------------------------------*/
1101 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1102 /*-----------------------------------------------------------------*/
1103 void pic16_aopOp (operand *op, iCode *ic, bool result)
1104 {
1105     asmop *aop;
1106     symbol *sym;
1107     int i;
1108
1109     if (!op)
1110         return ;
1111
1112     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1113
1114     /* if this a literal */
1115     if (IS_OP_LITERAL(op)) {
1116         op->aop = aop = newAsmop(AOP_LIT);
1117         aop->aopu.aop_lit = op->operand.valOperand;
1118         aop->size = getSize(operandType(op));
1119         return;
1120     }
1121
1122     {
1123       sym_link *type = operandType(op);
1124 #if 0
1125       if(IS_PTR_CONST(type))
1126 #else
1127       if(IS_CODEPTR(type))
1128 #endif
1129         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1130     }
1131
1132     /* if already has a asmop then continue */
1133     if (op->aop)
1134         return ;
1135
1136     /* if the underlying symbol has a aop */
1137     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1138       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1139         op->aop = OP_SYMBOL(op)->aop;
1140         return;
1141     }
1142
1143     /* if this is a true symbol */
1144     if (IS_TRUE_SYMOP(op)) {    
1145         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1146       op->aop = aopForSym(ic, op, result);
1147       return ;
1148     }
1149
1150     /* this is a temporary : this has
1151     only four choices :
1152     a) register
1153     b) spillocation
1154     c) rematerialize 
1155     d) conditional   
1156     e) can be a return use only */
1157
1158     sym = OP_SYMBOL(op);
1159
1160     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1161     /* if the type is a conditional */
1162     if (sym->regType == REG_CND) {
1163         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1164         aop->size = 0;
1165         return;
1166     }
1167
1168     /* if it is spilt then two situations
1169     a) is rematerialize 
1170     b) has a spill location */
1171     if (sym->isspilt || sym->nRegs == 0) {
1172
1173       DEBUGpic16_emitcode(";","%d",__LINE__);
1174         /* rematerialize it NOW */
1175         if (sym->remat) {
1176
1177             sym->aop = op->aop = aop = aopForRemat (op);
1178 //            aop->size = getSize(sym->type);
1179 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1180             return;
1181         }
1182
1183 #if 1
1184         if (sym->accuse) {
1185             int i;
1186             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1187             aop->size = getSize(sym->type);
1188             for ( i = 0 ; i < 1 ; i++ ) {
1189                 aop->aopu.aop_str[i] = accUse[i];
1190 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1191             }
1192             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1193             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1194             return;  
1195         }
1196 #endif
1197
1198 #if 1
1199         if (sym->ruonly ) {
1200           /*
1201           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1202           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1203           //pic16_allocDirReg (IC_LEFT(ic));
1204           aop->size = getSize(sym->type);
1205           */
1206
1207           unsigned i;
1208
1209           aop = op->aop = sym->aop = newAsmop(AOP_STR);
1210           aop->size = getSize(sym->type);
1211           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1212             aop->aopu.aop_str[i] = fReturn[i];
1213
1214           DEBUGpic16_emitcode(";","%d",__LINE__);
1215           return;
1216         }
1217 #endif
1218         /* else spill location  */
1219         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1220             /* force a new aop if sizes differ */
1221             sym->usl.spillLoc->aop = NULL;
1222         }
1223
1224 #if 0
1225         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1226                             __FUNCTION__,__LINE__,
1227                             sym->usl.spillLoc->rname,
1228                             sym->rname, sym->usl.spillLoc->offset);
1229 #endif
1230
1231         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1232         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1233         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1234                                           getSize(sym->type), 
1235                                           sym->usl.spillLoc->offset, op);
1236         aop->size = getSize(sym->type);
1237
1238         return;
1239     }
1240
1241     {
1242       sym_link *type = operandType(op);
1243 #if 0
1244       if(IS_PTR_CONST(type)) 
1245 #else
1246       if(IS_CODEPTR(type)) 
1247 #endif
1248         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1249     }
1250
1251     /* must be in a register */
1252     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1253     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1254     aop->size = sym->nRegs;
1255     for ( i = 0 ; i < sym->nRegs ;i++)
1256         aop->aopu.aop_reg[i] = sym->regs[i];
1257 }
1258
1259 /*-----------------------------------------------------------------*/
1260 /* pic16_freeAsmop - free up the asmop given to an operand               */
1261 /*----------------------------------------------------------------*/
1262 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1263 {   
1264     asmop *aop ;
1265
1266     if (!op)
1267         aop = aaop;
1268     else 
1269         aop = op->aop;
1270
1271     if (!aop)
1272         return ;
1273
1274     if (aop->freed)
1275         goto dealloc; 
1276
1277     aop->freed = 1;
1278
1279     /* depending on the asmop type only three cases need work AOP_RO
1280        , AOP_R1 && AOP_STK */
1281 #if 1
1282     switch (aop->type) {
1283         case AOP_FSR0 :
1284             if (_G.fsr0Pushed ) {
1285                 if (pop) {
1286                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1287                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1288 //                    pic16_emitcode ("pop","ar0");
1289                     _G.fsr0Pushed--;
1290                 }
1291             }
1292             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1293             break;
1294
1295         case AOP_FSR2 :
1296             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1297             break;
1298
1299         case AOP_R0 :
1300             if (_G.r0Pushed ) {
1301                 if (pop) {
1302                     pic16_emitcode ("pop","ar0");     
1303                     _G.r0Pushed--;
1304                 }
1305             }
1306             bitVectUnSetBit(ic->rUsed,R0_IDX);
1307             break;
1308
1309         case AOP_R1 :
1310             if (_G.r1Pushed ) {
1311                 if (pop) {
1312                     pic16_emitcode ("pop","ar1");
1313                     _G.r1Pushed--;
1314                 }
1315             }
1316             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1317             break;
1318
1319         case AOP_STA:
1320           {
1321             int i;
1322
1323               /* we must store the result on stack */
1324               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1325                 // operands on stack are accessible via "FSR2 + index" with index
1326                 // starting at 2 for arguments and growing from 0 downwards for
1327                 // local variables (index == 0 is not assigned so we add one here)
1328                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1329                 if (soffs <= 0) {
1330                   assert (soffs < 0);
1331                   soffs++;
1332                 } // if
1333                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1334                 for(i=0;i<aop->size;i++) {
1335                   /* initialise for stack access via frame pointer */
1336                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1337                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1338                         aop->aopu.stk.pop[i], pic16_popCopyReg(&pic16_pc_plusw2)));
1339                 }
1340         
1341                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1342               }
1343
1344               if(!_G.resDirect) {
1345                 for(i=0;i<aop->size;i++)
1346                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1347               }
1348               _G.resDirect = 0;
1349           }
1350           break;
1351 #if 0
1352         case AOP_STK :
1353         {
1354             int sz = aop->size;    
1355             int stk = aop->aopu.aop_stk + aop->size;
1356             bitVectUnSetBit(ic->rUsed,R0_IDX);
1357             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1358
1359             getFreePtr(ic,&aop,FALSE);
1360             
1361             if (options.stack10bit)
1362             {
1363                 /* I'm not sure what to do here yet... */
1364                 /* #STUB */
1365                 fprintf(stderr, 
1366                         "*** Warning: probably generating bad code for "
1367                         "10 bit stack mode.\n");
1368             }
1369             
1370             if (stk) {
1371                 pic16_emitcode ("mov","a,_bp");
1372                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1373                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1374             } else {
1375                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1376             }
1377
1378             while (sz--) {
1379                 pic16_emitcode("pop","acc");
1380                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1381                 if (!sz) break;
1382                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1383             }
1384             op->aop = aop;
1385             pic16_freeAsmop(op,NULL,ic,TRUE);
1386             if (_G.r0Pushed) {
1387                 pic16_emitcode("pop","ar0");
1388                 _G.r0Pushed--;
1389             }
1390
1391             if (_G.r1Pushed) {
1392                 pic16_emitcode("pop","ar1");
1393                 _G.r1Pushed--;
1394             }       
1395         }
1396 #endif
1397
1398     }
1399 #endif
1400
1401 dealloc:
1402     /* all other cases just dealloc */
1403     if (op ) {
1404         op->aop = NULL;
1405         if (IS_SYMOP(op)) {
1406             OP_SYMBOL(op)->aop = NULL;    
1407             /* if the symbol has a spill */
1408             if (SPIL_LOC(op))
1409                 SPIL_LOC(op)->aop = NULL;
1410         }
1411     }
1412 }
1413
1414 /*-----------------------------------------------------------------*/
1415 /* pic16_aopGet - for fetching value of the aop                          */
1416 /*-----------------------------------------------------------------*/
1417 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1418 {
1419     char *s = buffer ;
1420     char *rs;
1421
1422     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1423
1424     /* offset is greater than size then zero */
1425     if (offset > (aop->size - 1) &&
1426         aop->type != AOP_LIT)
1427         return zero;
1428
1429     /* depending on type */
1430     switch (aop->type) {
1431
1432     case AOP_FSR0:
1433     case AOP_FSR2:
1434       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1435       rs = Safe_calloc(1, strlen(s)+1);
1436       strcpy(rs, s);
1437       return (rs);
1438       
1439 #if 0
1440       /* if we need to increment it */
1441       while (offset > aop->coff)
1442         {
1443           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1444           aop->coff++;
1445         }
1446
1447       while (offset < aop->coff)
1448         {
1449           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1450           aop->coff--;
1451         }
1452       aop->coff = offset;
1453       if (aop->paged)
1454         {
1455           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1456           return (dname ? "acc" : "a");
1457         }
1458       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1459       rs = Safe_calloc (1, strlen (s) + 1);
1460       strcpy (rs, s);
1461       return rs;
1462 #endif
1463
1464         
1465     case AOP_IMMD:
1466         if (bit16) 
1467             sprintf (s,"%s",aop->aopu.aop_immd);
1468         else
1469             if (offset) 
1470                 sprintf(s,"(%s >> %d)",
1471                         aop->aopu.aop_immd,
1472                         offset*8);
1473             else
1474                 sprintf(s,"%s",
1475                         aop->aopu.aop_immd);
1476         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1477         rs = Safe_calloc(1,strlen(s)+1);
1478         strcpy(rs,s);   
1479         return rs;
1480         
1481     case AOP_DIR:
1482       if (offset) {
1483         sprintf(s,"(%s + %d)",
1484                 aop->aopu.aop_dir,
1485                 offset);
1486         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1487       } else
1488             sprintf(s,"%s",aop->aopu.aop_dir);
1489         rs = Safe_calloc(1,strlen(s)+1);
1490         strcpy(rs,s);   
1491         return rs;
1492         
1493     case AOP_REG:
1494       //if (dname) 
1495       //    return aop->aopu.aop_reg[offset]->dname;
1496       //else
1497             return aop->aopu.aop_reg[offset]->name;
1498         
1499     case AOP_CRY:
1500       //pic16_emitcode(";","%d",__LINE__);
1501       return aop->aopu.aop_dir;
1502         
1503     case AOP_ACC:
1504         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1505 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1506 //        assert( 0 );
1507 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1508         rs = Safe_strdup("WREG");
1509         return (rs);
1510
1511     case AOP_LIT:
1512         sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1513         rs = Safe_calloc(1,strlen(s)+1);
1514         strcpy(rs,s);   
1515         return rs;
1516         
1517     case AOP_STR:
1518         aop->coff = offset ;
1519         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1520             dname)
1521             return "acc";
1522         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1523         
1524         return aop->aopu.aop_str[offset];
1525         
1526     case AOP_PCODE:
1527       {
1528         pCodeOp *pcop = aop->aopu.pcop;
1529         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1530         if(pcop->name) {
1531           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1532           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1533           if (offset) {
1534             sprintf(s,"(%s + %d)", pcop->name, offset);
1535           } else {
1536             sprintf(s,"%s", pcop->name);
1537           }
1538         } else
1539           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1540
1541       }
1542       rs = Safe_calloc(1,strlen(s)+1);
1543       strcpy(rs,s);   
1544       return rs;
1545
1546     case AOP_STA:
1547         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1548         return (rs);
1549         
1550     case AOP_STK:
1551 //        pCodeOp *pcop = aop->aop
1552         break;
1553
1554     }
1555
1556     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1557     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1558            "aopget got unsupported aop->type");
1559     exit(0);
1560 }
1561
1562
1563
1564 /* lock has the following meaning: When allocating temporary registers
1565  * for stack variables storage, the value of the temporary register is
1566  * saved on stack. Its value is restored at the end. This procedure is
1567  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1568  * a possibility that before a call to pic16_aopOp, a temporary register
1569  * is allocated for a while and it is freed after some time, this will
1570  * mess the stack and values will not be restored properly. So use lock=1
1571  * to allocate temporary registers used internally by the programmer, and
1572  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1573  * to inform the compiler developer about a possible bug. This is an internal
1574  * feature for developing the compiler -- VR */
1575  
1576 int _TempReg_lock = 0;
1577 /*-----------------------------------------------------------------*/
1578 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1579 /*-----------------------------------------------------------------*/
1580 pCodeOp *pic16_popGetTempReg(int lock)
1581 {
1582   pCodeOp *pcop;
1583   symbol *cfunc;
1584
1585 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1586     if(_TempReg_lock) {
1587 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1588     }
1589     
1590     _TempReg_lock += lock;
1591     
1592     cfunc = currFunc;
1593     currFunc = NULL;
1594
1595     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1596     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1597       PCOR(pcop)->r->wasUsed=1;
1598       PCOR(pcop)->r->isFree=0;
1599
1600       /* push value on stack */
1601       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1602     }
1603
1604     currFunc = cfunc;
1605
1606   return pcop;
1607 }
1608
1609 /*-----------------------------------------------------------------*/
1610 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but   */
1611 /*                            don't save if inside v               */
1612 /*-----------------------------------------------------------------*/
1613 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1614 {
1615   pCodeOp *pcop;
1616   symbol *cfunc;
1617
1618 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1619
1620     if(_TempReg_lock) {
1621 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1622     }
1623
1624     _TempReg_lock += lock;
1625
1626     cfunc = currFunc;
1627     currFunc = NULL;
1628
1629     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1630     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1631       PCOR(pcop)->r->wasUsed=1;
1632       PCOR(pcop)->r->isFree=0;
1633
1634       if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1635       /* push value on stack */
1636         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1637       }
1638     }
1639
1640     currFunc = cfunc;
1641
1642   return pcop;
1643 }
1644
1645
1646 /*-----------------------------------------------------------------*/
1647 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1648 /*-----------------------------------------------------------------*/
1649 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1650 {
1651   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1652
1653   _TempReg_lock -= lock;
1654
1655   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1656     PCOR(pcop)->r->isFree = 1;
1657     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1658   }
1659 }
1660 /*-----------------------------------------------------------------*/
1661 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1662 /*-----------------------------------------------------------------*/
1663 pCodeOp *pic16_popGetLabel(unsigned int key)
1664 {
1665
1666   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1667
1668   if(key>max_key)
1669     max_key = key;
1670
1671   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1672 }
1673
1674 /*-----------------------------------------------------------------*/
1675 /* pic16_popCopyReg - copy a pcode operator                              */
1676 /*-----------------------------------------------------------------*/
1677 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1678 {
1679   pCodeOpReg *pcor;
1680
1681   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1682   pcor->pcop.type = pc->pcop.type;
1683   if(pc->pcop.name) {
1684     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1685       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1686   } else
1687     pcor->pcop.name = NULL;
1688
1689   pcor->r = pc->r;
1690   pcor->rIdx = pc->rIdx;
1691   pcor->r->wasUsed=1;
1692   pcor->instance = pc->instance;
1693
1694 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1695
1696   return PCOP(pcor);
1697 }
1698
1699 /*-----------------------------------------------------------------*/
1700 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1701 /*-----------------------------------------------------------------*/
1702 pCodeOp *pic16_popGetLit(int lit)
1703 {
1704   return pic16_newpCodeOpLit(lit);
1705 }
1706
1707 /*-----------------------------------------------------------------*/
1708 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1709 /*-----------------------------------------------------------------*/
1710 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1711 {
1712   return pic16_newpCodeOpLit2(lit, arg2);
1713 }
1714
1715
1716 /*-----------------------------------------------------------------*/
1717 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1718 /*-----------------------------------------------------------------*/
1719 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1720 {
1721   return pic16_newpCodeOpImmd(name, offset,index, 0);
1722 }
1723
1724
1725 /*-----------------------------------------------------------------*/
1726 /* pic16_popGet - asm operator to pcode operator conversion              */
1727 /*-----------------------------------------------------------------*/
1728 pCodeOp *pic16_popGetWithString(char *str)
1729 {
1730   pCodeOp *pcop;
1731
1732
1733   if(!str) {
1734     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1735     exit (1);
1736   }
1737
1738   pcop = pic16_newpCodeOp(str,PO_STR);
1739
1740   return pcop;
1741 }
1742
1743 /*-----------------------------------------------------------------*/
1744 /* pic16_popRegFromString -                                        */
1745 /*-----------------------------------------------------------------*/
1746 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1747 {
1748
1749   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1750   pcop->type = PO_DIR;
1751
1752   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1753   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1754
1755   if(!str)
1756     str = "BAD_STRING";
1757
1758   pcop->name = Safe_calloc(1,strlen(str)+1);
1759   strcpy(pcop->name,str);
1760
1761   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1762
1763   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1764
1765   /* make sure that register doesn't exist,
1766    * and operand isn't NULL
1767    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1768   if((PCOR(pcop)->r == NULL) 
1769     && (op)
1770     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1771 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1772 //              __FUNCTION__, __LINE__, str, size, offset);
1773
1774     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1775     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1776
1777   }
1778   PCOR(pcop)->instance = offset;
1779
1780   return pcop;
1781 }
1782
1783 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1784 {
1785   pCodeOp *pcop;
1786
1787 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1788
1789         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1790         PCOR(pcop)->rIdx = rIdx;
1791         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1792
1793         PCOR(pcop)->r->isFree = 0;
1794         PCOR(pcop)->r->wasUsed = 1;
1795
1796         pcop->type = PCOR(pcop)->r->pc_type;
1797
1798   return pcop;
1799 }
1800
1801 /*---------------------------------------------------------------------------------*/
1802 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1803 /*                 VR 030601                                                       */
1804 /*---------------------------------------------------------------------------------*/
1805 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1806 {
1807   pCodeOpReg2 *pcop2;
1808   pCodeOp *temp;
1809   
1810         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1811
1812         /* comment the following check, so errors to throw up */
1813 //      if(!pcop2)return NULL;
1814
1815         temp = pic16_popGet(aop_dst, offset);
1816         pcop2->pcop2 = temp;
1817         
1818   return PCOP(pcop2);
1819 }
1820
1821
1822
1823 /*--------------------------------------------------------------------------------.-*/
1824 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1825 /*                  VR 030601 , adapted by Hans Dorn                                */
1826 /*--------------------------------------------------------------------------------.-*/
1827 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1828 {
1829   pCodeOpReg2 *pcop2;
1830  
1831         pcop2 = (pCodeOpReg2 *)src;
1832         pcop2->pcop2 = dst;
1833         
1834         return PCOP(pcop2);
1835 }
1836
1837
1838
1839 /*---------------------------------------------------------------------------------*/
1840 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1841 /*                     movff instruction                                           */
1842 /*---------------------------------------------------------------------------------*/
1843 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1844 {
1845   pCodeOpReg2 *pcop2;
1846
1847         if(!noalloc) {
1848                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1849                 pcop2->pcop2 = pic16_popCopyReg(dst);
1850         } else {
1851                 /* the pCodeOp may be already allocated */
1852                 pcop2 = (pCodeOpReg2 *)(src);
1853                 pcop2->pcop2 = (pCodeOp *)(dst);
1854         }
1855
1856   return PCOP(pcop2);
1857 }
1858
1859
1860 /*-----------------------------------------------------------------*/
1861 /* pic16_popGet - asm operator to pcode operator conversion              */
1862 /*-----------------------------------------------------------------*/
1863 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1864 {
1865   //char *s = buffer ;
1866   char *rs;
1867   pCodeOp *pcop;
1868
1869     FENTRY2;
1870     /* offset is greater than
1871     size then zero */
1872
1873 //    if (offset > (aop->size - 1) &&
1874 //        aop->type != AOP_LIT)
1875 //      return NULL;  //zero;
1876
1877     /* depending on type */
1878     switch (aop->type) {
1879         
1880     case AOP_R0:
1881     case AOP_R1:
1882     case AOP_DPTR:
1883     case AOP_DPTR2:
1884         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1885         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1886         assert( 0 );
1887         return NULL;
1888
1889
1890     case AOP_FSR0:
1891     case AOP_FSR2:
1892       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1893       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
1894       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1895       PCOR(pcop)->r->wasUsed = 1;
1896       PCOR(pcop)->r->isFree = 0;
1897       
1898       PCOR(pcop)->instance = offset;
1899       pcop->type = PCOR(pcop)->r->pc_type;
1900       return (pcop);
1901
1902     case AOP_IMMD:
1903       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1904       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1905
1906     case AOP_STA:
1907       /* pCodeOp is already allocated from aopForSym */
1908         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1909         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1910           
1911       return (pcop);
1912       
1913     case AOP_ACC:
1914       {
1915         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1916
1917         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1918
1919         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1920         
1921         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1922         PCOR(pcop)->rIdx = rIdx;
1923         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1924         PCOR(pcop)->r->wasUsed=1;
1925         PCOR(pcop)->r->isFree=0;
1926
1927         PCOR(pcop)->instance = offset;
1928         pcop->type = PCOR(pcop)->r->pc_type;
1929 //      rs = aop->aopu.aop_reg[offset]->name;
1930 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1931         return pcop;
1932
1933
1934 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1935 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1936
1937 //      assert( 0 );
1938       }
1939         
1940     case AOP_DIR:
1941       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1942       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1943         
1944     case AOP_REG:
1945       {
1946         int rIdx;
1947         assert (aop && aop->aopu.aop_reg[offset] != NULL);
1948         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1949
1950         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1951         
1952         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1953 //      pcop->type = PO_GPR_REGISTER;
1954         PCOR(pcop)->rIdx = rIdx;
1955         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
1956         PCOR(pcop)->r->wasUsed=1;
1957         PCOR(pcop)->r->isFree=0;
1958
1959         PCOR(pcop)->instance = offset;
1960         pcop->type = PCOR(pcop)->r->pc_type;
1961         
1962         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s\n", __LINE__, dumpPicOptype(pcop->type));
1963         rs = aop->aopu.aop_reg[offset]->name;
1964         DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
1965         return pcop;
1966       }
1967
1968     case AOP_CRY:
1969         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1970
1971       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1972       PCOR(pcop)->instance = offset;
1973       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1974       //if(PCOR(pcop)->r == NULL)
1975       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1976       return pcop;
1977         
1978     case AOP_LIT:
1979         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1980       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1981
1982     case AOP_STR:
1983       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1984       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1985
1986       /*
1987       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1988       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1989       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1990       pcop->type = PCOR(pcop)->r->pc_type;
1991       pcop->name = PCOR(pcop)->r->name;
1992
1993       return pcop;
1994       */
1995
1996     case AOP_PCODE:
1997       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1998                           __LINE__, 
1999                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2000       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2001 #if 1
2002         switch( aop->aopu.pcop->type ) {
2003                 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
2004                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2005                 default:
2006                         assert( 0 );    /* should never reach here */;
2007         }
2008 #else
2009       PCOI(pcop)->offset = offset;
2010 #endif
2011       return pcop;
2012     }
2013
2014     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2015            "pic16_popGet got unsupported aop->type");
2016     exit(0);
2017 }
2018 /*-----------------------------------------------------------------*/
2019 /* pic16_aopPut - puts a string for a aop                                */
2020 /*-----------------------------------------------------------------*/
2021 void pic16_aopPut (asmop *aop, char *s, int offset)
2022 {
2023     char *d = buffer ;
2024     symbol *lbl ;
2025
2026     return;
2027
2028     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2029
2030     if (aop->size && offset > ( aop->size - 1)) {
2031         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2032                "pic16_aopPut got offset > aop->size");
2033         exit(0);
2034     }
2035
2036     /* will assign value to value */
2037     /* depending on where it is ofcourse */
2038     switch (aop->type) {
2039     case AOP_DIR:
2040       if (offset) {
2041         sprintf(d,"(%s + %d)",
2042                 aop->aopu.aop_dir,offset);
2043         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2044
2045       } else
2046             sprintf(d,"%s",aop->aopu.aop_dir);
2047         
2048         if (strcmp(d,s)) {
2049           DEBUGpic16_emitcode(";","%d",__LINE__);
2050           if(strcmp(s,"W"))
2051             pic16_emitcode("movf","%s,w",s);
2052           pic16_emitcode("movwf","%s",d);
2053
2054           if(strcmp(s,"W")) {
2055             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2056             if(offset >= aop->size) {
2057               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2058               break;
2059             } else
2060               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2061           }
2062
2063           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2064
2065
2066         }
2067         break;
2068         
2069     case AOP_REG:
2070       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2071         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2072           /*
2073             if (*s == '@'           ||
2074                 strcmp(s,"r0") == 0 ||
2075                 strcmp(s,"r1") == 0 ||
2076                 strcmp(s,"r2") == 0 ||
2077                 strcmp(s,"r3") == 0 ||
2078                 strcmp(s,"r4") == 0 ||
2079                 strcmp(s,"r5") == 0 ||
2080                 strcmp(s,"r6") == 0 || 
2081                 strcmp(s,"r7") == 0 )
2082                 pic16_emitcode("mov","%s,%s  ; %d",
2083                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2084             else
2085           */
2086
2087           if(strcmp(s,"W")==0 )
2088             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2089
2090           pic16_emitcode("movwf","%s",
2091                    aop->aopu.aop_reg[offset]->name);
2092
2093           if(strcmp(s,zero)==0) {
2094             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2095
2096           } else if(strcmp(s,"W")==0) {
2097             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2098             pcop->type = PO_GPR_REGISTER;
2099
2100             PCOR(pcop)->rIdx = -1;
2101             PCOR(pcop)->r = NULL;
2102
2103             DEBUGpic16_emitcode(";","%d",__LINE__);
2104             pcop->name = Safe_strdup(s);
2105             pic16_emitpcode(POC_MOVFW,pcop);
2106             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2107           } else if(strcmp(s,one)==0) {
2108             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2109             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2110           } else {
2111             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2112           }
2113         }
2114         break;
2115         
2116     case AOP_DPTR:
2117     case AOP_DPTR2:
2118     
2119     if (aop->type == AOP_DPTR2)
2120     {
2121         genSetDPTR(1);
2122     }
2123     
2124         if (aop->code) {
2125             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2126                    "pic16_aopPut writting to code space");
2127             exit(0);
2128         }
2129         
2130         while (offset > aop->coff) {
2131             aop->coff++;
2132             pic16_emitcode ("inc","dptr");
2133         }
2134         
2135         while (offset < aop->coff) {
2136             aop->coff-- ;
2137             pic16_emitcode("lcall","__decdptr");
2138         }
2139         
2140         aop->coff = offset;
2141         
2142         /* if not in accumulater */
2143         MOVA(s);        
2144         
2145         pic16_emitcode ("movx","@dptr,a");
2146         
2147     if (aop->type == AOP_DPTR2)
2148     {
2149         genSetDPTR(0);
2150     }
2151         break;
2152         
2153     case AOP_R0:
2154     case AOP_R1:
2155         while (offset > aop->coff) {
2156             aop->coff++;
2157             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2158         }
2159         while (offset < aop->coff) {
2160             aop->coff-- ;
2161             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2162         }
2163         aop->coff = offset;
2164         
2165         if (aop->paged) {
2166             MOVA(s);           
2167             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2168             
2169         } else
2170             if (*s == '@') {
2171                 MOVA(s);
2172                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2173             } else
2174                 if (strcmp(s,"r0") == 0 ||
2175                     strcmp(s,"r1") == 0 ||
2176                     strcmp(s,"r2") == 0 ||
2177                     strcmp(s,"r3") == 0 ||
2178                     strcmp(s,"r4") == 0 ||
2179                     strcmp(s,"r5") == 0 ||
2180                     strcmp(s,"r6") == 0 || 
2181                     strcmp(s,"r7") == 0 ) {
2182                     char buffer[10];
2183                     sprintf(buffer,"a%s",s);
2184                     pic16_emitcode("mov","@%s,%s",
2185                              aop->aopu.aop_ptr->name,buffer);
2186                 } else
2187                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2188         
2189         break;
2190         
2191     case AOP_STK:
2192         if (strcmp(s,"a") == 0)
2193             pic16_emitcode("push","acc");
2194         else
2195             pic16_emitcode("push","%s",s);
2196         
2197         break;
2198         
2199     case AOP_CRY:
2200         /* if bit variable */
2201         if (!aop->aopu.aop_dir) {
2202             pic16_emitcode("clr","a");
2203             pic16_emitcode("rlc","a");
2204         } else {
2205             if (s == zero) 
2206                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2207             else
2208                 if (s == one)
2209                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2210                 else
2211                     if (!strcmp(s,"c"))
2212                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2213                     else {
2214                         lbl = newiTempLabel(NULL);
2215                         
2216                         if (strcmp(s,"a")) {
2217                             MOVA(s);
2218                         }
2219                         pic16_emitcode("clr","c");
2220                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2221                         pic16_emitcode("cpl","c");
2222                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2223                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2224                     }
2225         }
2226         break;
2227         
2228     case AOP_STR:
2229         aop->coff = offset;
2230         if (strcmp(aop->aopu.aop_str[offset],s))
2231             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2232         break;
2233         
2234     case AOP_ACC:
2235         aop->coff = offset;
2236         if (!offset && (strcmp(s,"acc") == 0))
2237             break;
2238         
2239         if (strcmp(aop->aopu.aop_str[offset],s))
2240             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2241         break;
2242
2243     default :
2244         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2245 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2246 //             "pic16_aopPut got unsupported aop->type");
2247 //      exit(0);    
2248     }    
2249
2250 }
2251
2252 /*-----------------------------------------------------------------*/
2253 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2254 /*-----------------------------------------------------------------*/
2255 void pic16_mov2w (asmop *aop, int offset)
2256 {
2257   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2258
2259   if(is_LitAOp(aop))
2260     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2261   else
2262     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2263 }
2264
2265 static void mov2f(asmop *dst, asmop *src, int offset)
2266 {
2267   if(is_LitAOp(src)) {
2268     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2269     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2270   } else {
2271     if(pic16_sameRegsOfs(src, dst, offset))return;
2272     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2273                       pic16_popGet(dst, offset)));
2274   }
2275 }
2276
2277 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2278 {
2279   if(is_LitAOp(src)) {
2280     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2281     pic16_emitpcode(POC_MOVWF, dst);
2282   } else {
2283     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2284   }
2285 }
2286
2287 void pic16_testStackOverflow(void)
2288 {
2289 #define GSTACK_TEST_NAME        "__gstack_test"
2290
2291   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2292   
2293   {
2294     symbol *sym;
2295
2296       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2297       strcpy(sym->rname, GSTACK_TEST_NAME);
2298       checkAddSym(&externs, sym);
2299   }
2300
2301 }
2302
2303 /* push pcop into stack */
2304 void pic16_pushpCodeOp(pCodeOp *pcop)
2305 {
2306 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2307   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
2308   if(pic16_options.gstack)
2309     pic16_testStackOverflow();
2310     
2311 }
2312
2313 /* pop pcop from stack */
2314 void pic16_poppCodeOp(pCodeOp *pcop)
2315 {
2316   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
2317   if(pic16_options.gstack)
2318     pic16_testStackOverflow();
2319 }
2320
2321
2322 /*-----------------------------------------------------------------*/
2323 /* pushw - pushes wreg to stack                                    */
2324 /*-----------------------------------------------------------------*/
2325 void pushw(void)
2326 {
2327   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2328   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2329   if(pic16_options.gstack)
2330     pic16_testStackOverflow();
2331 }
2332
2333                 
2334 /*-----------------------------------------------------------------*/
2335 /* pushaop - pushes aop to stack                                   */
2336 /*-----------------------------------------------------------------*/
2337 void pushaop(asmop *aop, int offset)
2338 {
2339   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2340
2341   if(is_LitAOp(aop)) {
2342     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2343     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2344   } else {
2345     pic16_emitpcode(POC_MOVFF,
2346       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg(&pic16_pc_postdec1)));
2347   }
2348
2349 //  pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
2350   if(pic16_options.gstack)
2351     pic16_testStackOverflow();
2352 }
2353
2354 /*-----------------------------------------------------------------*/
2355 /* popaop - pops aop from stack                                    */
2356 /*-----------------------------------------------------------------*/
2357 void popaop(asmop *aop, int offset)
2358 {
2359   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2360   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
2361   if(pic16_options.gstack)
2362     pic16_testStackOverflow();
2363 }
2364
2365 void popaopidx(asmop *aop, int offset, int index)
2366 {
2367   int ofs=1;
2368
2369     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2370
2371     if(STACK_MODEL_LARGE)ofs++;
2372
2373     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2374     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
2375     if(pic16_options.gstack)
2376       pic16_testStackOverflow();
2377 }
2378
2379 #if !(USE_GENERIC_SIGNED_SHIFT)
2380 /*-----------------------------------------------------------------*/
2381 /* reAdjustPreg - points a register back to where it should        */
2382 /*-----------------------------------------------------------------*/
2383 static void reAdjustPreg (asmop *aop)
2384 {
2385     int size ;
2386
2387     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2388     aop->coff = 0;
2389     if ((size = aop->size) <= 1)
2390         return ;
2391     size-- ;
2392     switch (aop->type) {
2393         case AOP_R0 :
2394         case AOP_R1 :
2395             while (size--)
2396                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2397             break;          
2398         case AOP_DPTR :
2399         case AOP_DPTR2:
2400             if (aop->type == AOP_DPTR2)
2401             {
2402                 genSetDPTR(1);
2403             } 
2404             while (size--)
2405             {
2406                 pic16_emitcode("lcall","__decdptr");
2407             }
2408                 
2409             if (aop->type == AOP_DPTR2)
2410             {
2411                 genSetDPTR(0);
2412             }                
2413             break;  
2414
2415     }   
2416
2417 }
2418 #endif
2419
2420 #if 0
2421 /*-----------------------------------------------------------------*/
2422 /* opIsGptr: returns non-zero if the passed operand is             */   
2423 /* a generic pointer type.                                         */
2424 /*-----------------------------------------------------------------*/ 
2425 static int opIsGptr(operand *op)
2426 {
2427     sym_link *type = operandType(op);
2428     
2429     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2430     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2431     {
2432         return 1;
2433     }
2434     return 0;        
2435 }
2436 #endif
2437
2438 /*-----------------------------------------------------------------*/
2439 /* pic16_getDataSize - get the operand data size                         */
2440 /*-----------------------------------------------------------------*/
2441 int pic16_getDataSize(operand *op)
2442 {
2443     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2444
2445
2446     return AOP_SIZE(op);
2447
2448     // tsd- in the pic port, the genptr size is 1, so this code here
2449     // fails. ( in the 8051 port, the size was 4).
2450 #if 0
2451     int size;
2452     size = AOP_SIZE(op);
2453     if (size == GPTRSIZE)
2454     {
2455         sym_link *type = operandType(op);
2456         if (IS_GENPTR(type))
2457         {
2458             /* generic pointer; arithmetic operations
2459              * should ignore the high byte (pointer type).
2460              */
2461             size--;
2462     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2463         }
2464     }
2465     return size;
2466 #endif
2467 }
2468
2469 /*-----------------------------------------------------------------*/
2470 /* pic16_outAcc - output Acc                                             */
2471 /*-----------------------------------------------------------------*/
2472 void pic16_outAcc(operand *result)
2473 {
2474   int size,offset;
2475   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2476   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2477
2478
2479   size = pic16_getDataSize(result);
2480   if(size){
2481     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2482     size--;
2483     offset = 1;
2484     /* unsigned or positive */
2485     while(size--)
2486       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2487   }
2488
2489 }
2490
2491 /*-----------------------------------------------------------------*/
2492 /* pic16_outBitC - output a bit C                                  */
2493 /*                 Move to result the value of Carry flag -- VR    */
2494 /*-----------------------------------------------------------------*/
2495 void pic16_outBitC(operand *result)
2496 {
2497   int i;
2498
2499     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2500
2501     /* if the result is bit */
2502     if (AOP_TYPE(result) == AOP_CRY) {
2503         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2504         pic16_aopPut(AOP(result),"c",0);
2505     } else {
2506
2507         i = AOP_SIZE(result);
2508         while(i--) {
2509                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2510         }
2511         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2512     }
2513 }
2514
2515 /*-----------------------------------------------------------------*/
2516 /* pic16_outBitOp - output a bit from Op                           */
2517 /*                 Move to result the value of set/clr op -- VR    */
2518 /*-----------------------------------------------------------------*/
2519 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2520 {
2521   int i;
2522
2523     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2524
2525     /* if the result is bit */
2526     if (AOP_TYPE(result) == AOP_CRY) {
2527         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2528         pic16_aopPut(AOP(result),"c",0);
2529     } else {
2530
2531         i = AOP_SIZE(result);
2532         while(i--) {
2533                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2534         }
2535         pic16_emitpcode(POC_RRCF, pcop);          
2536         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2537     }
2538 }
2539
2540 /*-----------------------------------------------------------------*/
2541 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2542 /*-----------------------------------------------------------------*/
2543 void pic16_toBoolean(operand *oper)
2544 {
2545     int size = AOP_SIZE(oper) - 1;
2546     int offset = 1;
2547
2548     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2549
2550     if ( AOP_TYPE(oper) != AOP_ACC) {
2551       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2552     }
2553     while (size--) {
2554       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2555     }
2556 }
2557
2558
2559 #if !defined(GEN_Not)
2560 /*-----------------------------------------------------------------*/
2561 /* genNot - generate code for ! operation                          */
2562 /*-----------------------------------------------------------------*/
2563 static void pic16_genNot (iCode *ic)
2564 {
2565   symbol *tlbl;
2566   int size;
2567
2568   FENTRY;
2569   /* assign asmOps to operand & result */
2570   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2571   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2572
2573   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2574   /* if in bit space then a special case */
2575   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2576     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2577       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2578       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2579     } else {
2580       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2581       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2582       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2583     }
2584     goto release;
2585   }
2586
2587   size = AOP_SIZE(IC_LEFT(ic));
2588   if(size == 1) {
2589     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2590     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2591     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2592     goto release;
2593   }
2594   pic16_toBoolean(IC_LEFT(ic));
2595
2596   tlbl = newiTempLabel(NULL);
2597   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2598   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2599   pic16_outBitC(IC_RESULT(ic));
2600
2601  release:    
2602   /* release the aops */
2603   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2604   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2605 }
2606 #endif
2607
2608
2609 #if !defined(GEN_Cpl)
2610 /*-----------------------------------------------------------------*/
2611 /* genCpl - generate code for complement                           */
2612 /*-----------------------------------------------------------------*/
2613 static void pic16_genCpl (iCode *ic)
2614 {
2615   int offset = 0;
2616   int size ;
2617
2618     FENTRY;
2619     /* assign asmOps to operand & result */
2620     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2621     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2622
2623     /* if both are in bit space then 
2624     a special case */
2625     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2626         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2627
2628         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2629         pic16_emitcode("cpl","c"); 
2630         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2631         goto release; 
2632     } 
2633
2634     size = AOP_SIZE(IC_RESULT(ic));
2635     while (size--) {
2636 /*
2637         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2638         MOVA(l);       
2639         pic16_emitcode("cpl","a");
2640         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2641 */
2642         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2643               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2644         } else {
2645                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2646                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2647         }
2648         offset++;
2649
2650     }
2651
2652
2653 release:
2654     /* release the aops */
2655     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2656     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2657 }
2658 #endif
2659
2660 /*-----------------------------------------------------------------*/
2661 /* genUminusFloat - unary minus for floating points                */
2662 /*-----------------------------------------------------------------*/
2663 static void genUminusFloat(operand *op,operand *result)
2664 {
2665   int size ,offset =0 ;
2666   
2667     FENTRY;
2668     /* for this we just need to flip the 
2669     first it then copy the rest in place */
2670     size = AOP_SIZE(op);
2671
2672     while(size--) {
2673       mov2f(AOP(result), AOP(op), offset);
2674       offset++;
2675     }
2676     
2677     /* toggle the MSB's highest bit */
2678     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2679 }
2680
2681 /*-----------------------------------------------------------------*/
2682 /* genUminus - unary minus code generation                         */
2683 /*-----------------------------------------------------------------*/
2684 static void genUminus (iCode *ic)
2685 {
2686   int size, i;
2687   sym_link *optype, *rtype;
2688
2689     FENTRY;     
2690     
2691     /* assign asmops */
2692     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2693     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2694
2695     /* if both in bit space then special case */
2696     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2697       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2698         
2699         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2700         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2701         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2702         goto release; 
2703     } 
2704
2705     optype = operandType(IC_LEFT(ic));
2706     rtype = operandType(IC_RESULT(ic));
2707
2708     /* if float then do float stuff */
2709     if (IS_FLOAT(optype)) {
2710       genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2711       goto release;
2712     }
2713
2714     /* otherwise subtract from zero by taking the 2's complement */
2715     size = AOP_SIZE(IC_LEFT(ic));
2716
2717     for(i=0; i<size; i++) {
2718       if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2719         pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2720       else {
2721         pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2722         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2723       }
2724     }
2725
2726     pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2727     for(i=1; i<size; i++) {
2728       emitSKPNZ;
2729       pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2730     }
2731
2732 release:
2733     /* release the aops */
2734     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2735     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2736 }
2737
2738 #if 0
2739 /*-----------------------------------------------------------------*/
2740 /* saveRegisters - will look for a call and save the registers     */
2741 /*-----------------------------------------------------------------*/
2742 static void saveRegisters(iCode *lic) 
2743 {
2744     int i;
2745     iCode *ic;
2746     bitVect *rsave;
2747     sym_link *dtype;
2748
2749     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2750     /* look for call */
2751     for (ic = lic ; ic ; ic = ic->next) 
2752         if (ic->op == CALL || ic->op == PCALL)
2753             break;
2754
2755     if (!ic) {
2756         fprintf(stderr,"found parameter push with no function call\n");
2757         return ;
2758     }
2759
2760     /* if the registers have been saved already then
2761     do nothing */
2762     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2763         return ;
2764
2765     /* find the registers in use at this time 
2766     and push them away to safety */
2767     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2768                           ic->rUsed);
2769
2770     ic->regsSaved = 1;
2771     if (options.useXstack) {
2772         if (bitVectBitValue(rsave,R0_IDX))
2773             pic16_emitcode("mov","b,r0");
2774         pic16_emitcode("mov","r0,%s",spname);
2775         for (i = 0 ; i < pic16_nRegs ; i++) {
2776             if (bitVectBitValue(rsave,i)) {
2777                 if (i == R0_IDX)
2778                     pic16_emitcode("mov","a,b");
2779                 else
2780                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2781                 pic16_emitcode("movx","@r0,a");
2782                 pic16_emitcode("inc","r0");
2783             }
2784         }
2785         pic16_emitcode("mov","%s,r0",spname);
2786         if (bitVectBitValue(rsave,R0_IDX))
2787             pic16_emitcode("mov","r0,b");           
2788     }// else
2789     //for (i = 0 ; i < pic16_nRegs ; i++) {
2790     //    if (bitVectBitValue(rsave,i))
2791     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2792     //}
2793
2794     dtype = operandType(IC_LEFT(ic));
2795     if (currFunc && dtype && 
2796         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2797         IFFUNC_ISISR(currFunc->type) &&
2798         !ic->bankSaved) 
2799
2800         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2801
2802 }
2803 /*-----------------------------------------------------------------*/
2804 /* unsaveRegisters - pop the pushed registers                      */
2805 /*-----------------------------------------------------------------*/
2806 static void unsaveRegisters (iCode *ic)
2807 {
2808     int i;
2809     bitVect *rsave;
2810
2811     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2812     /* find the registers in use at this time 
2813     and push them away to safety */
2814     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2815                           ic->rUsed);
2816     
2817     if (options.useXstack) {
2818         pic16_emitcode("mov","r0,%s",spname);   
2819         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2820             if (bitVectBitValue(rsave,i)) {
2821                 pic16_emitcode("dec","r0");
2822                 pic16_emitcode("movx","a,@r0");
2823                 if (i == R0_IDX)
2824                     pic16_emitcode("mov","b,a");
2825                 else
2826                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2827             }       
2828
2829         }
2830         pic16_emitcode("mov","%s,r0",spname);
2831         if (bitVectBitValue(rsave,R0_IDX))
2832             pic16_emitcode("mov","r0,b");
2833     } //else
2834     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2835     //    if (bitVectBitValue(rsave,i))
2836     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2837     //}
2838
2839 }  
2840 #endif
2841
2842 #if 0  // patch 14
2843 /*-----------------------------------------------------------------*/
2844 /* pushSide -                                                      */
2845 /*-----------------------------------------------------------------*/
2846 static void pushSide(operand * oper, int size)
2847 {
2848         int offset = 0;
2849     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2850         while (size--) {
2851                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2852                 if (AOP_TYPE(oper) != AOP_REG &&
2853                     AOP_TYPE(oper) != AOP_DIR &&
2854                     strcmp(l,"a") ) {
2855                         pic16_emitcode("mov","a,%s",l);
2856                         pic16_emitcode("push","acc");
2857                 } else
2858                         pic16_emitcode("push","%s",l);
2859         }
2860 }
2861 #endif // patch 14
2862
2863 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2864 {
2865   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2866     pic16_emitpcode(POC_MOVFW, src);
2867     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2868   } else {
2869     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2870         src, pic16_popGet(AOP(op), offset)));
2871   }
2872 }
2873
2874
2875 /*-----------------------------------------------------------------*/
2876 /* assignResultValue - assign results to oper, rescall==1 is       */
2877 /*                     called from genCall() or genPcall()         */
2878 /*-----------------------------------------------------------------*/
2879 static void assignResultValue(operand * oper, int rescall)
2880 {
2881   int size = AOP_SIZE(oper);
2882   int offset=0;
2883   
2884     FENTRY2;
2885 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2886     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2887
2888     if(rescall) {
2889       /* assign result from a call/pcall function() */
2890                 
2891       /* function results are stored in a special order,
2892        * see top of file with Function return policy, or manual */
2893
2894       if(size <= 4) {
2895         /* 8-bits, result in WREG */
2896         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2897                         
2898         if(size>1) {
2899           /* 16-bits, result in PRODL:WREG */
2900           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2901         }
2902                         
2903         if(size>2) {
2904           /* 24-bits, result in PRODH:PRODL:WREG */
2905           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2906         }
2907                         
2908         if(size>3) {
2909           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2910           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2911         }
2912       
2913       } else {
2914         /* >32-bits, result on stack, and FSR0 points to beginning.
2915          * Fix stack when done */
2916         /* FIXME FIXME */
2917 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2918         while (size--) {
2919 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2920 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2921                 
2922           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2923           GpsuedoStkPtr++;
2924         }
2925                         
2926         /* fix stack */
2927         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2928         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2929         if(STACK_MODEL_LARGE) {
2930           emitSKPNC;
2931           pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2932         }
2933       }                 
2934     } else {
2935       int areg = 0;             /* matching argument register */
2936       
2937 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2938       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2939
2940
2941       /* its called from genReceive (probably) -- VR */
2942       /* I hope this code will not be called from somewhere else in the future! 
2943        * We manually set the pseudo stack pointer in genReceive. - dw
2944        */
2945       if(!GpsuedoStkPtr && _G.useWreg) {
2946 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2947
2948         /* The last byte in the assignment is in W */
2949         if(areg <= GpsuedoStkPtr) {
2950           size--;
2951           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2952           offset++;
2953 //          debugf("receive from WREG\n", 0);
2954         }
2955         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
2956       }
2957 //      GpsuedoStkPtr++;
2958       _G.stack_lat = AOP_SIZE(oper)-1;
2959
2960       while (size) {
2961         size--;
2962         GpsuedoStkPtr++;
2963         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
2964 //        debugf("receive from STACK\n", 0);
2965         offset++;
2966       }
2967     }
2968 }
2969
2970
2971 /*-----------------------------------------------------------------*/
2972 /* genIpush - generate code for pushing this gets a little complex */
2973 /*-----------------------------------------------------------------*/
2974 static void genIpush (iCode *ic)
2975 {
2976 //  int size, offset=0;
2977
2978   FENTRY;
2979   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2980
2981   if(ic->parmPush) {
2982     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2983
2984     /* send to stack as normal */
2985     addSet(&_G.sendSet,ic);
2986 //    addSetHead(&_G.sendSet,ic);
2987     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2988   }
2989
2990         
2991 #if 0
2992     int size, offset = 0 ;
2993     char *l;
2994
2995
2996     /* if this is not a parm push : ie. it is spill push 
2997     and spill push is always done on the local stack */
2998     if (!ic->parmPush) {
2999
3000         /* and the item is spilt then do nothing */
3001         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3002             return ;
3003
3004         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3005         size = AOP_SIZE(IC_LEFT(ic));
3006         /* push it on the stack */
3007         while(size--) {
3008             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3009             if (*l == '#') {
3010                 MOVA(l);
3011                 l = "acc";
3012             }
3013             pic16_emitcode("push","%s",l);
3014         }
3015         return ;        
3016     }
3017
3018     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3019 #endif
3020 }
3021
3022 /*-----------------------------------------------------------------*/
3023 /* genIpop - recover the registers: can happen only for spilling   */
3024 /*-----------------------------------------------------------------*/
3025 static void genIpop (iCode *ic)
3026 {
3027   FENTRY;
3028   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3029 #if 0
3030     int size,offset ;
3031
3032
3033     /* if the temp was not pushed then */
3034     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3035         return ;
3036
3037     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3038     size = AOP_SIZE(IC_LEFT(ic));
3039     offset = (size-1);
3040     while (size--) 
3041         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3042                                    FALSE,TRUE));
3043
3044     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3045 #endif
3046 }
3047
3048 #if 0
3049 /*-----------------------------------------------------------------*/
3050 /* unsaverbank - restores the resgister bank from stack            */
3051 /*-----------------------------------------------------------------*/
3052 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3053 {
3054   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3055 #if 0
3056     int i;
3057     asmop *aop ;
3058     regs *r = NULL;
3059
3060     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3061     if (popPsw) {
3062         if (options.useXstack) {
3063             aop = newAsmop(0);
3064             r = getFreePtr(ic,&aop,FALSE);
3065             
3066             
3067             pic16_emitcode("mov","%s,_spx",r->name);
3068             pic16_emitcode("movx","a,@%s",r->name);
3069             pic16_emitcode("mov","psw,a");
3070             pic16_emitcode("dec","%s",r->name);
3071             
3072         }else
3073             pic16_emitcode ("pop","psw");
3074     }
3075
3076     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3077         if (options.useXstack) {       
3078             pic16_emitcode("movx","a,@%s",r->name);
3079             //pic16_emitcode("mov","(%s+%d),a",
3080             //       regspic16[i].base,8*bank+regspic16[i].offset);
3081             pic16_emitcode("dec","%s",r->name);
3082
3083         } else 
3084           pic16_emitcode("pop",""); //"(%s+%d)",
3085         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3086     }
3087
3088     if (options.useXstack) {
3089
3090         pic16_emitcode("mov","_spx,%s",r->name);
3091         pic16_freeAsmop(NULL,aop,ic,TRUE);
3092
3093     }
3094 #endif 
3095 }
3096
3097 /*-----------------------------------------------------------------*/
3098 /* saverbank - saves an entire register bank on the stack          */
3099 /*-----------------------------------------------------------------*/
3100 static void saverbank (int bank, iCode *ic, bool pushPsw)
3101 {
3102   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3103 #if 0
3104     int i;
3105     asmop *aop ;
3106     regs *r = NULL;
3107
3108     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3109     if (options.useXstack) {
3110
3111         aop = newAsmop(0);
3112         r = getFreePtr(ic,&aop,FALSE);  
3113         pic16_emitcode("mov","%s,_spx",r->name);
3114
3115     }
3116
3117     for (i = 0 ; i < pic16_nRegs ;i++) {
3118         if (options.useXstack) {
3119             pic16_emitcode("inc","%s",r->name);
3120             //pic16_emitcode("mov","a,(%s+%d)",
3121             //         regspic16[i].base,8*bank+regspic16[i].offset);
3122             pic16_emitcode("movx","@%s,a",r->name);           
3123         } else 
3124           pic16_emitcode("push","");// "(%s+%d)",
3125                      //regspic16[i].base,8*bank+regspic16[i].offset);
3126     }
3127     
3128     if (pushPsw) {
3129         if (options.useXstack) {
3130             pic16_emitcode("mov","a,psw");
3131             pic16_emitcode("movx","@%s,a",r->name);     
3132             pic16_emitcode("inc","%s",r->name);
3133             pic16_emitcode("mov","_spx,%s",r->name);       
3134             pic16_freeAsmop (NULL,aop,ic,TRUE);
3135             
3136         } else
3137             pic16_emitcode("push","psw");
3138         
3139         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3140     }
3141     ic->bankSaved = 1;
3142 #endif
3143 }
3144 #endif  /* 0 */
3145
3146
3147 static int wparamCmp(void *p1, void *p2)
3148 {
3149   return (!strcmp((char *)p1, (char *)p2));
3150 }
3151
3152 int inWparamList(char *s)
3153 {
3154   return isinSetWith(wparamList, s, wparamCmp);
3155
3156
3157
3158 /*-----------------------------------------------------------------*/
3159 /* genCall - generates a call statement                            */
3160 /*-----------------------------------------------------------------*/
3161 static void genCall (iCode *ic)
3162 {
3163   sym_link *ftype;   
3164   int stackParms=0;
3165   int use_wreg=0;
3166   int inwparam=0;
3167   char *fname;
3168   
3169     FENTRY;
3170
3171     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3172     /* if caller saves & we have not saved then */
3173 //    if (!ic->regsSaved)
3174 //      saveRegisters(ic);
3175
3176         /* initialise stackParms for IPUSH pushes */
3177 //      stackParms = psuedoStkPtr;
3178 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3179     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3180     inwparam = inWparamList(OP_SYMBOL(IC_LEFT(ic))->name);
3181
3182 #if 0
3183     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3184 #endif
3185
3186     /* if send set is not empty the assign */
3187     if (_G.sendSet) {
3188       iCode *sic;
3189       int psuedoStkPtr=-1; 
3190       int firstTimeThruLoop = 1;
3191
3192
3193         /* reverse sendSet if function is not reentrant */
3194         if(!IFFUNC_ISREENT(ftype))
3195           _G.sendSet = reverseSet(_G.sendSet);
3196
3197         /* First figure how many parameters are getting passed */
3198         stackParms = 0;
3199         use_wreg = 0;
3200         
3201         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3202           int size;
3203 //          int offset = 0;
3204
3205             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3206             size = AOP_SIZE(IC_LEFT(sic));
3207
3208             stackParms += size;
3209
3210             /* pass the last byte through WREG */
3211             if(inwparam) {
3212
3213               while (size--) {
3214                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3215                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3216                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3217
3218                 if(!firstTimeThruLoop) {
3219                   /* If this is not the first time we've been through the loop
3220                    * then we need to save the parameter in a temporary
3221                    * register. The last byte of the last parameter is
3222                    * passed in W. */
3223
3224                   pushw();
3225 //                  --psuedoStkPtr;             // sanity check
3226                   use_wreg = 1;
3227                 }
3228                 
3229                 firstTimeThruLoop=0;
3230
3231                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3232
3233 //                offset++;
3234               }
3235             } else {
3236               /* all arguments are passed via stack */
3237               use_wreg = 0;
3238
3239               while (size--) {
3240                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3241                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3242                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3243
3244 //                pushaop(AOP(IC_LEFT(sic)), size);
3245                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3246                 pushw();
3247               }
3248             }
3249
3250             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3251           }
3252
3253           if(inwparam) {
3254             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3255               pushw();  /* save last parameter to stack if functions has varargs */
3256               use_wreg = 0;
3257             } else
3258               use_wreg = 1;
3259           } else use_wreg = 0;
3260
3261           _G.stackRegSet = _G.sendSet;
3262           _G.sendSet = NULL;
3263     }
3264
3265     /* make the call */
3266     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3267
3268     GpsuedoStkPtr=0;
3269     
3270     /* if we need to assign a result value */
3271     if ((IS_ITEMP(IC_RESULT(ic))
3272           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3273               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3274         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3275
3276       _G.accInUse++;
3277       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3278       _G.accInUse--;
3279
3280       assignResultValue(IC_RESULT(ic), 1);
3281
3282       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3283                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3284                 
3285       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3286     }
3287
3288     if(!stackParms && ic->parmBytes) {
3289       stackParms = ic->parmBytes;
3290     }
3291       
3292     stackParms -= use_wreg;
3293     
3294     if(stackParms>0) {
3295       if(stackParms == 1) {
3296         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1l));
3297       } else {
3298         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3299         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3300       }
3301       if(STACK_MODEL_LARGE) {
3302         emitSKPNC;
3303         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3304       }
3305     }
3306
3307 #if 0
3308     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3309 #endif
3310
3311     /* adjust the stack for parameters if required */
3312 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3313
3314 #if 0
3315       /* if register bank was saved then pop them */
3316       if (ic->bankSaved)
3317         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3318
3319       /* if we hade saved some registers then unsave them */
3320       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3321         unsaveRegisters (ic);
3322 #endif
3323 }
3324
3325
3326
3327 /*-----------------------------------------------------------------*/
3328 /* genPcall - generates a call by pointer statement                */
3329 /*            new version, created from genCall - HJD              */
3330 /*-----------------------------------------------------------------*/
3331 static void genPcall (iCode *ic)
3332 {
3333   sym_link *ftype, *fntype;
3334   int stackParms=0;
3335   symbol *retlbl = newiTempLabel(NULL);
3336   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3337   
3338     FENTRY;
3339
3340     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3341     fntype = operandType( IC_LEFT(ic) )->next;
3342
3343     /* if send set is not empty the assign */
3344     if (_G.sendSet) {
3345       iCode *sic;
3346       int psuedoStkPtr=-1; 
3347
3348       /* reverse sendSet if function is not reentrant */
3349       if(!IFFUNC_ISREENT(fntype))
3350         _G.sendSet = reverseSet(_G.sendSet);
3351
3352       stackParms = 0;
3353       
3354       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3355         int size;
3356
3357           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3358           size = AOP_SIZE(IC_LEFT(sic));
3359           stackParms += size;
3360
3361           /* all parameters are passed via stack, since WREG is clobbered
3362            * by the calling sequence */
3363           while (size--) {
3364             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3365             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3366             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3367
3368             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3369             pushw();
3370           }
3371
3372           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3373       }
3374
3375       _G.stackRegSet = _G.sendSet;
3376       _G.sendSet = NULL;
3377     }
3378
3379     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3380
3381     // push return address
3382     // push $ on return stack, then replace with retlbl
3383
3384     pic16_emitpcodeNULLop(POC_PUSH);
3385
3386     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3387     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3388     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3389     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3390     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3391     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3392
3393     /* make the call by writing the pointer into pc */
3394     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3395     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3396
3397     // note: MOVFF to PCL not allowed
3398     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3399     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3400
3401
3402     /* return address is here: (X) */
3403     pic16_emitpLabelFORCE(retlbl->key);
3404
3405     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3406
3407     GpsuedoStkPtr=0;
3408     /* if we need assign a result value */
3409     if ((IS_ITEMP(IC_RESULT(ic))
3410           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3411               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3412         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3413
3414       _G.accInUse++;
3415       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3416       _G.accInUse--;
3417
3418       assignResultValue(IC_RESULT(ic), 1);
3419
3420       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3421               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3422                 
3423       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3424     }
3425
3426 //    stackParms -= use_wreg;
3427     
3428     if(stackParms>0) {
3429       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3430       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3431       if(STACK_MODEL_LARGE) {
3432         /* this implies that stackParms < 256 !!! -- VR */
3433         emitSKPNC;
3434         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3435       }
3436     }
3437 }
3438
3439 /*-----------------------------------------------------------------*/
3440 /* resultRemat - result  is rematerializable                       */
3441 /*-----------------------------------------------------------------*/
3442 static int resultRemat (iCode *ic)
3443 {
3444   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3445   if (SKIP_IC(ic) || ic->op == IFX)
3446     return 0;
3447
3448   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3449     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3450     if (sym->remat && !POINTER_SET(ic)) 
3451       return 1;
3452   }
3453
3454   return 0;
3455 }
3456
3457 #if defined(__BORLANDC__) || defined(_MSC_VER)
3458 #define STRCASECMP stricmp
3459 #else
3460 #define STRCASECMP strcasecmp
3461 #endif
3462
3463 #if 0
3464 /*-----------------------------------------------------------------*/
3465 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3466 /*-----------------------------------------------------------------*/
3467 static bool inExcludeList(char *s)
3468 {
3469   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3470     int i =0;
3471     
3472     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3473     if (options.excludeRegs[i] &&
3474     STRCASECMP(options.excludeRegs[i],"none") == 0)
3475         return FALSE ;
3476
3477     for ( i = 0 ; options.excludeRegs[i]; i++) {
3478         if (options.excludeRegs[i] &&
3479         STRCASECMP(s,options.excludeRegs[i]) == 0)
3480             return TRUE;
3481     }
3482     return FALSE ;
3483 }
3484 #endif
3485
3486 /*-----------------------------------------------------------------*/
3487 /* genFunction - generated code for function entry                 */
3488 /*-----------------------------------------------------------------*/
3489 static void genFunction (iCode *ic)
3490 {
3491   symbol *sym;
3492   sym_link *ftype;
3493   
3494     FENTRY;
3495     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3496
3497     pic16_labelOffset += (max_key+4);
3498     max_key=0;
3499     GpsuedoStkPtr=0;
3500     _G.nRegsSaved = 0;
3501         
3502     ftype = operandType(IC_LEFT(ic));
3503     sym = OP_SYMBOL(IC_LEFT(ic));
3504
3505     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3506       /* create an absolute section at the interrupt vector:
3507        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3508       symbol *asym;
3509       char asymname[128];
3510       pBlock *apb;
3511
3512         {
3513           int i, found=-1;
3514
3515             sym = OP_SYMBOL( IC_LEFT(ic));
3516             for(i=0;i<=2;i++) {
3517               if(interrupts[i]->name
3518                     && !STRCASECMP(interrupts[i]->name, sym->name)) {
3519                   found = i;
3520                   break;
3521               }
3522             }
3523                         
3524             if(found == -1) {
3525               fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3526                             __FILE__, __LINE__, sym->name);
3527               assert( 0 );
3528             }
3529             _G.interruptvector = found;
3530         }
3531
3532         sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3533         asym = newSymbol(asymname, 0);
3534
3535         apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3536         pic16_addpBlock( apb );
3537
3538         pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3539         pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3540         pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3541                 
3542         /* mark the end of this tiny function */
3543         pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3544
3545         {
3546           absSym *abSym;
3547
3548             abSym = Safe_calloc(1, sizeof(absSym));
3549             strcpy(abSym->name, asymname);
3550
3551             switch( _G.interruptvector ) {
3552               case 0: abSym->address = 0x000000; break;
3553               case 1: abSym->address = 0x000008; break;
3554               case 2: abSym->address = 0x000018; break;
3555             }
3556
3557             /* relocate interrupt vectors if needed */
3558             abSym->address += pic16_options.ivt_loc;
3559
3560             addSet(&absSymSet, abSym);
3561         }
3562     }
3563
3564     /* create the function header */
3565     pic16_emitcode(";","-----------------------------------------");
3566     pic16_emitcode(";"," function %s",sym->name);
3567     pic16_emitcode(";","-----------------------------------------");
3568
3569     pic16_emitcode("","%s:",sym->rname);
3570     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3571
3572
3573     {
3574       absSym *ab;
3575
3576         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3577           if(!strcmp(ab->name, sym->rname)) {
3578             pic16_pBlockConvert2Absolute(pb);
3579             break;
3580           }
3581         }
3582     }
3583
3584
3585     if(IFFUNC_ISNAKED(ftype)) {
3586       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3587       return;
3588     }
3589         
3590     /* if critical function then turn interrupts off */
3591     if (IFFUNC_ISCRITICAL(ftype)) {
3592       //pic16_emitcode("clr","ea");
3593     }
3594
3595     _G.fregsUsed = sym->regsUsed;
3596
3597     /* if this is an interrupt service routine then
3598      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3599     if (IFFUNC_ISISR(sym->type)) {
3600         _G.usefastretfie = 1;   /* use shadow registers by default */
3601         
3602         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3603         if(!(_G.interruptvector == 1)) {
3604           /* do not save WREG,STATUS,BSR for high priority interrupts
3605            * because they are stored in the hardware shadow registers already */
3606           _G.usefastretfie = 0;
3607           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3608           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3609           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3610         }
3611
3612         /* these should really be optimized somehow, because not all
3613          * interrupt handlers modify them */
3614         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3615         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3616         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3617         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3618         
3619 //        pic16_pBlockConvert2ISR(pb);
3620                 
3621     }
3622
3623     /* emit code to setup stack frame if user enabled,
3624      * and function is not main() */
3625          
3626     //fprintf(stderr, "function name: %s\n", sym->name);
3627     if(strcmp(sym->name, "main")) {
3628       if(1  /*!options.ommitFramePtr || sym->regsUsed*/) {
3629         /* setup the stack frame */
3630         if(STACK_MODEL_LARGE)
3631           pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2h));
3632         pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2l));
3633 //        pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3634         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3635         if(STACK_MODEL_LARGE)
3636           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3637       }
3638     }
3639
3640     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3641           && sym->stack) {
3642
3643       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3644
3645       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3646       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_fsr1l));
3647       emitSKPC;
3648       pic16_emitpcode(POC_DECF, pic16_popCopyReg(&pic16_pc_fsr1h));
3649     }
3650           
3651     if(inWparamList(sym->name)) {
3652       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3653         _G.useWreg = 0;
3654       else
3655         _G.useWreg = 1;
3656     } else
3657       _G.useWreg = 0;
3658
3659     /* if callee-save to be used for this function
3660      * then save the registers being used in this function */
3661 //    if (IFFUNC_CALLEESAVES(sym->type))
3662     {
3663       int i;
3664
3665         /* if any registers used */
3666         if (sym->regsUsed) {
3667           /* save the registers used */
3668           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3669           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3670           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3671             if (bitVectBitValue(sym->regsUsed,i)) {
3672               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3673               _G.nRegsSaved++;
3674
3675               if(!pic16_regWithIdx(i)->wasUsed) {
3676                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3677                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3678                 pic16_regWithIdx(i)->wasUsed = 1;
3679               }
3680             }
3681           }
3682           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3683         }
3684     }
3685         
3686     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3687 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3688 }
3689
3690 /*-----------------------------------------------------------------*/
3691 /* genEndFunction - generates epilogue for functions               */
3692 /*-----------------------------------------------------------------*/
3693 static void genEndFunction (iCode *ic)
3694 {
3695   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3696
3697     FENTRY;
3698
3699     if(IFFUNC_ISNAKED(sym->type)) {
3700       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3701       return;
3702     }
3703
3704     _G.stack_lat = 0;
3705
3706     /* add code for ISCRITICAL */
3707     if(IFFUNC_ISCRITICAL(sym->type)) {
3708       /* if critical function, turn on interrupts */
3709       
3710       /* TODO: add code here -- VR */
3711     }
3712     
3713 //    sym->regsUsed = _G.fregsUsed;
3714     
3715     /* now we need to restore the registers */
3716     /* if any registers used */
3717     if (sym->regsUsed) {
3718       int i;
3719
3720         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3721         /* restore registers used */
3722         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3723         for ( i = sym->regsUsed->size; i >= 0; i--) {
3724           if (bitVectBitValue(sym->regsUsed,i)) {
3725             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3726             _G.nRegsSaved--;
3727           }
3728         }
3729         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3730
3731     }
3732
3733     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3734           && sym->stack) {
3735       if (sym->stack == 1) {
3736         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg(&pic16_pc_fsr1l));
3737         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h));
3738       } else {
3739         // we have to add more than one...
3740         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc1)); // this holds a return value!
3741         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3742         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(&pic16_pc_fsr1l));
3743         emitSKPNC;
3744         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h));
3745         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3746         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_plusw1)); // this holds a retrun value!
3747       }
3748     }
3749
3750     if(strcmp(sym->name, "main")) {
3751       if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3752         /* restore stack frame */
3753         if(STACK_MODEL_LARGE)
3754           pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2h ));
3755 //          pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3756         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2l ));
3757 //        pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3758       }
3759     }
3760
3761     _G.useWreg = 0;
3762
3763     if (IFFUNC_ISISR(sym->type)) {
3764       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3765       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3766       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3767       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3768
3769       if(!(_G.interruptvector == 1)) {
3770         /* do not restore interrupt vector for WREG,STATUS,BSR
3771          * for high priority interrupt, see genFunction */
3772         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3773         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3774         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3775       }
3776       _G.interruptvector = 0;           /* sanity check */
3777
3778
3779       /* if debug then send end of function */
3780 /*      if (options.debug && currFunc)  */
3781       if (currFunc) {
3782         debugFile->writeEndFunction (currFunc, ic, 1);
3783       }
3784         
3785       if(_G.usefastretfie)
3786         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3787       else
3788         pic16_emitpcodeNULLop(POC_RETFIE);
3789
3790       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3791       
3792       _G.usefastretfie = 0;
3793       return;
3794     }
3795
3796     if (IFFUNC_ISCRITICAL(sym->type)) {
3797       pic16_emitcode("setb","ea");
3798     }
3799
3800     /* if debug then send end of function */
3801     if (currFunc) {
3802       debugFile->writeEndFunction (currFunc, ic, 1);
3803     }
3804
3805     /* insert code to restore stack frame, if user enabled it
3806      * and function is not main() */
3807          
3808
3809     pic16_emitpcodeNULLop(POC_RETURN);
3810
3811     /* Mark the end of a function */
3812     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3813 }
3814
3815
3816 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3817 {
3818   if(is_LitOp(op)) {
3819     unsigned long lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3820       if(lit == 0) {
3821         pic16_emitpcode(POC_CLRF, dest);
3822       } else {
3823         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3824         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3825       }
3826   } else {
3827     if(dest->type == PO_WREG && (offset == 0)) {
3828       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3829       return;
3830     }
3831     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3832   }
3833 }
3834
3835 /*-----------------------------------------------------------------*/
3836 /* genRet - generate code for return statement                     */
3837 /*-----------------------------------------------------------------*/
3838 static void genRet (iCode *ic)
3839 {
3840   int size;
3841   operand *left;
3842
3843     FENTRY;
3844         /* if we have no return value then
3845          * just generate the "ret" */
3846         
3847         if (!IC_LEFT(ic)) 
3848                 goto jumpret;       
3849     
3850         /* we have something to return then
3851          * move the return value into place */
3852         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3853         size = AOP_SIZE(IC_LEFT(ic));
3854
3855         if(size <= 4) {
3856                 if(size>3) {
3857                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3858 //                      pic16_emitpcode(POC_MOVFF,
3859 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3860                 }
3861                 if(size>2) {
3862                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3863 //                      pic16_emitpcode(POC_MOVFF,
3864 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3865                 }
3866                 if(size>1) {
3867                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3868 //                      pic16_emitpcode(POC_MOVFF,
3869 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3870                 }
3871
3872 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3873
3874                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3875 //              pic16_emitpcode(POC_MOVFF,
3876 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3877
3878         } else {
3879                 /* >32-bits, setup stack and FSR0 */
3880                 while (size--) {
3881 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3882 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3883
3884                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3885
3886 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3887                         GpsuedoStkPtr++;
3888                 }
3889                         
3890                 /* setup FSR0 */
3891                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3892                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3893
3894                 if(STACK_MODEL_LARGE) {
3895                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3896                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3897                 } else {
3898                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3899                 }
3900         }
3901                                 
3902 #if 0
3903         /* old code, left here for reference -- VR */    
3904         while (size--) {
3905           char *l ;
3906
3907                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3908                         /* #NOCHANGE */
3909                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3910                         pic16_emitpcomment("push %s",l);
3911                         pushed++;
3912                 } else {
3913                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3914                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3915                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3916                         
3917                         if (strcmp(fReturn[offset],l)) {
3918                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3919                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3920                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3921                                 } else {
3922                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3923                                 }
3924                                 
3925                                 if(size) {
3926                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3927                                 }
3928                                 offset++;
3929                         }
3930                 }
3931         }    
3932
3933         if (pushed) {
3934                 while(pushed) {
3935                         pushed--;
3936                         if (strcmp(fReturn[pushed],"a"))
3937                                 pic16_emitcode("pop",fReturn[pushed]);
3938                         else
3939                                 pic16_emitcode("pop","acc");
3940                 }
3941         }
3942 #endif
3943
3944
3945         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3946     
3947 jumpret:
3948         /* generate a jump to the return label
3949          * if the next is not the return statement */
3950         if (!(ic->next && ic->next->op == LABEL
3951                 && IC_LABEL(ic->next) == returnLabel)) {
3952         
3953                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3954                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3955         }
3956 }
3957
3958 /*-----------------------------------------------------------------*/
3959 /* genLabel - generates a label                                    */
3960 /*-----------------------------------------------------------------*/
3961 static void genLabel (iCode *ic)
3962 {
3963   FENTRY;
3964
3965   /* special case never generate */
3966   if (IC_LABEL(ic) == entryLabel)
3967     return ;
3968
3969   pic16_emitpLabel(IC_LABEL(ic)->key);
3970 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3971 }
3972
3973 /*-----------------------------------------------------------------*/
3974 /* genGoto - generates a goto                                      */
3975 /*-----------------------------------------------------------------*/
3976 //tsd
3977 static void genGoto (iCode *ic)
3978 {
3979   FENTRY;
3980   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3981 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3982 }
3983
3984
3985 /*-----------------------------------------------------------------*/
3986 /* genMultbits :- multiplication of bits                           */
3987 /*-----------------------------------------------------------------*/
3988 static void genMultbits (operand *left, 
3989                          operand *right, 
3990                          operand *result)
3991 {
3992   FENTRY;
3993
3994   if(!pic16_sameRegs(AOP(result),AOP(right)))
3995     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3996
3997   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3998   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3999   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4000
4001 }
4002
4003
4004 /*-----------------------------------------------------------------*/
4005 /* genMultOneByte : 8 bit multiplication & division                */
4006 /*-----------------------------------------------------------------*/
4007 static void genMultOneByte (operand *left,
4008                             operand *right,
4009                             operand *result)
4010 {
4011
4012   FENTRY;
4013   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4014   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4015
4016   /* (if two literals, the value is computed before) */
4017   /* if one literal, literal on the right */
4018   if (AOP_TYPE(left) == AOP_LIT){
4019     operand *t = right;
4020     right = left;
4021     left = t;
4022   }
4023
4024         /* size is already checked in genMult == 1 */
4025 //      size = AOP_SIZE(result);
4026
4027         if (AOP_TYPE(right) == AOP_LIT){
4028                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4029                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4030                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4031                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4032         } else {
4033                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4034                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4035                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4036                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4037         }
4038         
4039         pic16_genMult8X8_8 (left, right,result);
4040 }
4041
4042 /*-----------------------------------------------------------------*/
4043 /* genMultOneWord : 16 bit multiplication                          */
4044 /*-----------------------------------------------------------------*/
4045 static void genMultOneWord (operand *left,
4046                             operand *right,
4047                             operand *result)
4048 {
4049   FENTRY;
4050   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4051   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4052
4053   /* (if two literals, the value is computed before)
4054    * if one literal, literal on the right */
4055   if (AOP_TYPE(left) == AOP_LIT){
4056     operand *t = right;
4057     right = left;
4058     left = t;
4059   }
4060
4061   /* size is checked already == 2 */
4062 //  size = AOP_SIZE(result);
4063
4064   if (AOP_TYPE(right) == AOP_LIT) {
4065     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4066       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4067       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4068       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4069   } else {
4070     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4071       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4072       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4073       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4074   }
4075         
4076   pic16_genMult16X16_16(left, right,result);
4077 }
4078
4079 /*-----------------------------------------------------------------*/
4080 /* genMultOneLong : 32 bit multiplication                          */
4081 /*-----------------------------------------------------------------*/
4082 static void genMultOneLong (operand *left,
4083                             operand *right,
4084                             operand *result)
4085 {
4086   FENTRY;
4087   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4088   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4089
4090   /* (if two literals, the value is computed before)
4091    * if one literal, literal on the right */
4092   if (AOP_TYPE(left) == AOP_LIT){
4093     operand *t = right;
4094     right = left;
4095     left = t;
4096   }
4097
4098   /* size is checked already == 4 */
4099 //  size = AOP_SIZE(result);
4100
4101   if (AOP_TYPE(right) == AOP_LIT) {
4102     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4103         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4104         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4105         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4106   } else {
4107     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4108         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4109         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4110         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4111   }
4112         
4113   pic16_genMult32X32_32(left, right,result);
4114 }
4115
4116
4117
4118 /*-----------------------------------------------------------------*/
4119 /* genMult - generates code for multiplication                     */
4120 /*-----------------------------------------------------------------*/
4121 static void genMult (iCode *ic)
4122 {
4123   operand *left = IC_LEFT(ic);
4124   operand *right = IC_RIGHT(ic);
4125   operand *result= IC_RESULT(ic);   
4126
4127     FENTRY;
4128         /* assign the amsops */
4129         pic16_aopOp (left,ic,FALSE);
4130         pic16_aopOp (right,ic,FALSE);
4131         pic16_aopOp (result,ic,TRUE);
4132
4133         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4134
4135         /* special cases first *
4136         * both are bits */
4137         if (AOP_TYPE(left) == AOP_CRY
4138                 && AOP_TYPE(right)== AOP_CRY) {
4139                 genMultbits(left,right,result);
4140           goto release ;
4141         }
4142
4143         /* if both are of size == 1 */
4144         if(AOP_SIZE(left) == 1
4145                 && AOP_SIZE(right) == 1) {
4146                 genMultOneByte(left,right,result);
4147           goto release ;
4148         }
4149
4150         /* if both are of size == 2 */
4151         if(AOP_SIZE(left) == 2
4152                 && AOP_SIZE(right) == 2) {
4153                 genMultOneWord(left, right, result);
4154           goto release;
4155         }
4156         
4157         /* if both are of size == 4 */
4158         if(AOP_SIZE(left) == 4
4159                 && AOP_SIZE(right) == 4) {
4160                 genMultOneLong(left, right, result);
4161           goto release;
4162         }
4163         
4164         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4165
4166
4167         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4168         /* should have been converted to function call */
4169         assert(0) ;
4170
4171 release :
4172         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4173         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4174         pic16_freeAsmop(result,NULL,ic,TRUE); 
4175 }
4176
4177 /*-----------------------------------------------------------------*/
4178 /* genDivbits :- division of bits                                  */
4179 /*-----------------------------------------------------------------*/
4180 static void genDivbits (operand *left, 
4181                         operand *right, 
4182                         operand *result)
4183 {
4184   char *l;
4185
4186     FENTRY;
4187     /* the result must be bit */    
4188     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4189     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4190
4191     MOVA(l);    
4192
4193     pic16_emitcode("div","ab");
4194     pic16_emitcode("rrc","a");
4195     pic16_aopPut(AOP(result),"c",0);
4196 }
4197
4198 /*-----------------------------------------------------------------*/
4199 /* genDivOneByte : 8 bit division                                  */
4200 /*-----------------------------------------------------------------*/
4201 static void genDivOneByte (operand *left,
4202                            operand *right,
4203                            operand *result)
4204 {
4205   sym_link *opetype = operandType(result);
4206   char *l ;
4207   symbol *lbl ;
4208   int size,offset;
4209
4210         /* result = divident / divisor
4211          * - divident may be a register or a literal,
4212          * - divisor may be a register or a literal,
4213          * so there are 3 cases (literal / literal is optimized
4214          * by the front-end) to handle.
4215          * In addition we must handle signed and unsigned, which
4216          * result in 6 final different cases -- VR */
4217
4218     FENTRY;
4219     
4220     size = AOP_SIZE(result) - 1;
4221     offset = 1;
4222     /* signed or unsigned */
4223     if (SPEC_USIGN(opetype)) {
4224       pCodeOp *pct1,    /* count */
4225                 *pct2,  /* reste */
4226                 *pct3;  /* temp */
4227       symbol *label1, *label2, *label3;;
4228
4229
4230         /* unsigned is easy */
4231
4232         pct1 = pic16_popGetTempReg(1);
4233         pct2 = pic16_popGetTempReg(1);
4234         pct3 = pic16_popGetTempReg(1);
4235         
4236         label1 = newiTempLabel(NULL);
4237         label2 = newiTempLabel(NULL);
4238         label3 = newiTempLabel(NULL);
4239
4240         /* the following algorithm is extracted from divuint.c */
4241
4242         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4243         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4244         
4245         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4246
4247         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4248         
4249         pic16_emitpLabel(label1->key);
4250         
4251         emitCLRC;
4252         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4253
4254
4255         emitCLRC;
4256         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4257         
4258
4259         emitSKPNC;
4260         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4261         
4262         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4263         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4264         
4265         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4266         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4267         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4268         
4269         pic16_emitpLabel( label3->key );
4270         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4271         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4272         
4273         
4274
4275         pic16_emitpLabel(label2->key);
4276         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4277         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4278         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4279         
4280         /* result is in wreg */
4281         if(AOP_TYPE(result) != AOP_ACC)
4282                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4283
4284         pic16_popReleaseTempReg( pct3, 1);
4285         pic16_popReleaseTempReg( pct2, 1);
4286         pic16_popReleaseTempReg( pct1, 1);
4287
4288         return ;
4289     }
4290
4291     /* signed is a little bit more difficult */
4292
4293     /* save the signs of the operands */
4294     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4295     MOVA(l);    
4296     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4297     pic16_emitcode("push","acc"); /* save it on the stack */
4298
4299     /* now sign adjust for both left & right */
4300     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4301     MOVA(l);       
4302     lbl = newiTempLabel(NULL);
4303     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4304     pic16_emitcode("cpl","a");   
4305     pic16_emitcode("inc","a");
4306     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4307     pic16_emitcode("mov","b,a");
4308
4309     /* sign adjust left side */
4310     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4311     MOVA(l);
4312
4313     lbl = newiTempLabel(NULL);
4314     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4315     pic16_emitcode("cpl","a");
4316     pic16_emitcode("inc","a");
4317     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4318
4319     /* now the division */
4320     pic16_emitcode("div","ab");
4321     /* we are interested in the lower order
4322     only */
4323     pic16_emitcode("mov","b,a");
4324     lbl = newiTempLabel(NULL);
4325     pic16_emitcode("pop","acc");   
4326     /* if there was an over flow we don't 
4327     adjust the sign of the result */
4328     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4329     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4330     CLRC;
4331     pic16_emitcode("clr","a");
4332     pic16_emitcode("subb","a,b");
4333     pic16_emitcode("mov","b,a");
4334     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4335
4336     /* now we are done */
4337     pic16_aopPut(AOP(result),"b",0);
4338     if(size > 0){
4339         pic16_emitcode("mov","c,b.7");
4340         pic16_emitcode("subb","a,acc");   
4341     }
4342     while (size--)
4343         pic16_aopPut(AOP(result),"a",offset++);
4344
4345 }
4346
4347 /*-----------------------------------------------------------------*/
4348 /* genDiv - generates code for division                            */
4349 /*-----------------------------------------------------------------*/
4350 static void genDiv (iCode *ic)
4351 {
4352     operand *left = IC_LEFT(ic);
4353     operand *right = IC_RIGHT(ic);
4354     operand *result= IC_RESULT(ic);   
4355
4356
4357         /* Division is a very lengthy algorithm, so it is better
4358          * to call support routines than inlining algorithm.
4359          * Division functions written here just in case someone
4360          * wants to inline and not use the support libraries -- VR */
4361
4362     FENTRY;
4363     
4364     /* assign the amsops */
4365     pic16_aopOp (left,ic,FALSE);
4366     pic16_aopOp (right,ic,FALSE);
4367     pic16_aopOp (result,ic,TRUE);
4368
4369     /* special cases first */
4370     /* both are bits */
4371     if (AOP_TYPE(left) == AOP_CRY &&
4372         AOP_TYPE(right)== AOP_CRY) {
4373         genDivbits(left,right,result);
4374         goto release ;
4375     }
4376
4377     /* if both are of size == 1 */
4378     if (AOP_SIZE(left) == 1 &&
4379         AOP_SIZE(right) == 1 ) {
4380         genDivOneByte(left,right,result);
4381         goto release ;
4382     }
4383
4384     /* should have been converted to function call */
4385     assert(0);
4386 release :
4387     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4388     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4389     pic16_freeAsmop(result,NULL,ic,TRUE); 
4390 }
4391
4392 /*-----------------------------------------------------------------*/
4393 /* genModbits :- modulus of bits                                   */
4394 /*-----------------------------------------------------------------*/
4395 static void genModbits (operand *left, 
4396                         operand *right, 
4397                         operand *result)
4398 {
4399   char *l;
4400
4401     FENTRY;  
4402     
4403     werror(W_POSSBUG2, __FILE__, __LINE__);
4404     /* the result must be bit */    
4405     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4406     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4407
4408     MOVA(l);       
4409
4410     pic16_emitcode("div","ab");
4411     pic16_emitcode("mov","a,b");
4412     pic16_emitcode("rrc","a");
4413     pic16_aopPut(AOP(result),"c",0);
4414 }
4415
4416 /*-----------------------------------------------------------------*/
4417 /* genModOneByte : 8 bit modulus                                   */
4418 /*-----------------------------------------------------------------*/
4419 static void genModOneByte (operand *left,
4420                            operand *right,
4421                            operand *result)
4422 {
4423   sym_link *opetype = operandType(result);
4424   char *l ;
4425   symbol *lbl ;
4426
4427     FENTRY;
4428     werror(W_POSSBUG2, __FILE__, __LINE__);
4429
4430     /* signed or unsigned */
4431     if (SPEC_USIGN(opetype)) {
4432         /* unsigned is easy */
4433         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4434         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4435         MOVA(l);    
4436         pic16_emitcode("div","ab");
4437         pic16_aopPut(AOP(result),"b",0);
4438         return ;
4439     }
4440
4441     /* signed is a little bit more difficult */
4442
4443     /* save the signs of the operands */
4444     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4445     MOVA(l);
4446
4447     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4448     pic16_emitcode("push","acc"); /* save it on the stack */
4449
4450     /* now sign adjust for both left & right */
4451     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4452     MOVA(l);
4453
4454     lbl = newiTempLabel(NULL);
4455     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4456     pic16_emitcode("cpl","a");   
4457     pic16_emitcode("inc","a");
4458     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4459     pic16_emitcode("mov","b,a"); 
4460
4461     /* sign adjust left side */
4462     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4463     MOVA(l);
4464
4465     lbl = newiTempLabel(NULL);
4466     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4467     pic16_emitcode("cpl","a");   
4468     pic16_emitcode("inc","a");
4469     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4470
4471     /* now the multiplication */
4472     pic16_emitcode("div","ab");
4473     /* we are interested in the lower order
4474     only */
4475     lbl = newiTempLabel(NULL);
4476     pic16_emitcode("pop","acc");   
4477     /* if there was an over flow we don't 
4478     adjust the sign of the result */
4479     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4480     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4481     CLRC ;
4482     pic16_emitcode("clr","a");
4483     pic16_emitcode("subb","a,b");
4484     pic16_emitcode("mov","b,a");
4485     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4486
4487     /* now we are done */
4488     pic16_aopPut(AOP(result),"b",0);
4489
4490 }
4491
4492 /*-----------------------------------------------------------------*/
4493 /* genMod - generates code for division                            */
4494 /*-----------------------------------------------------------------*/
4495 static void genMod (iCode *ic)
4496 {
4497   operand *left = IC_LEFT(ic);
4498   operand *right = IC_RIGHT(ic);
4499   operand *result= IC_RESULT(ic);  
4500
4501     FENTRY;
4502     
4503     /* assign the amsops */
4504     pic16_aopOp (left,ic,FALSE);
4505     pic16_aopOp (right,ic,FALSE);
4506     pic16_aopOp (result,ic,TRUE);
4507
4508     /* special cases first */
4509     /* both are bits */
4510     if (AOP_TYPE(left) == AOP_CRY &&
4511         AOP_TYPE(right)== AOP_CRY) {
4512         genModbits(left,right,result);
4513         goto release ;
4514     }
4515
4516     /* if both are of size == 1 */
4517     if (AOP_SIZE(left) == 1 &&
4518         AOP_SIZE(right) == 1 ) {
4519         genModOneByte(left,right,result);
4520         goto release ;
4521     }
4522
4523     /* should have been converted to function call */
4524     assert(0);
4525
4526 release :
4527     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4528     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4529     pic16_freeAsmop(result,NULL,ic,TRUE); 
4530 }
4531
4532 /*-----------------------------------------------------------------*/
4533 /* genIfxJump :- will create a jump depending on the ifx           */
4534 /*-----------------------------------------------------------------*/
4535 /*
4536   note: May need to add parameter to indicate when a variable is in bit space.
4537 */
4538 static void genIfxJump (iCode *ic, char *jval)
4539 {
4540   FENTRY;
4541   
4542     /* if true label then we jump if condition
4543     supplied is true */
4544     if ( IC_TRUE(ic) ) {
4545
4546         if(strcmp(jval,"a") == 0)
4547           emitSKPZ;
4548         else if (strcmp(jval,"c") == 0)
4549           emitSKPNC;
4550         else {
4551           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4552           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4553         }
4554
4555         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4556         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4557
4558     }
4559     else {
4560         /* false label is present */
4561         if(strcmp(jval,"a") == 0)
4562           emitSKPNZ;
4563         else if (strcmp(jval,"c") == 0)
4564           emitSKPC;
4565         else {
4566           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4567           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4568         }
4569
4570         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4571         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4572
4573     }
4574
4575
4576     /* mark the icode as generated */
4577     ic->generated = 1;
4578 }
4579
4580 #if 0
4581 // not needed ATM
4582
4583 /*-----------------------------------------------------------------*/
4584 /* genSkip                                                         */
4585 /*-----------------------------------------------------------------*/
4586 static void genSkip(iCode *ifx,int status_bit)
4587 {
4588   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4589   if(!ifx)
4590     return;
4591
4592   if ( IC_TRUE(ifx) ) {
4593     switch(status_bit) {
4594     case 'z':
4595       emitSKPNZ;
4596       break;
4597
4598     case 'c':
4599       emitSKPNC;
4600       break;
4601
4602     case 'd':
4603       emitSKPDC;
4604       break;
4605
4606     }
4607
4608     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4609     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4610
4611   } else {
4612
4613     switch(status_bit) {
4614
4615     case 'z':
4616       emitSKPZ;
4617       break;
4618
4619     case 'c':
4620       emitSKPC;
4621       break;
4622
4623     case 'd':
4624       emitSKPDC;
4625       break;
4626     }
4627     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4628     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4629
4630   }
4631
4632 }
4633 #endif
4634
4635 /*-----------------------------------------------------------------*/
4636 /* genSkipc                                                        */
4637 /*-----------------------------------------------------------------*/
4638 static void genSkipc(resolvedIfx *rifx)
4639 {
4640   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4641   
4642   if(!rifx)
4643     return;
4644
4645   if(rifx->condition)
4646     emitSKPC;
4647   else
4648     emitSKPNC;
4649
4650   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4651   rifx->generated = 1;
4652 }
4653
4654 #if !(USE_SIMPLE_GENCMP)
4655 /*-----------------------------------------------------------------*/
4656 /* genSkipz2                                                       */
4657 /*-----------------------------------------------------------------*/
4658 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4659 {
4660   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4661   
4662   if(!rifx)
4663     return;
4664
4665   if( (rifx->condition ^ invert_condition) & 1)
4666     emitSKPZ;
4667   else
4668     emitSKPNZ;
4669
4670   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4671   rifx->generated = 1;
4672 }
4673 #endif
4674
4675 #if 0
4676 /*-----------------------------------------------------------------*/
4677 /* genSkipz                                                        */
4678 /*-----------------------------------------------------------------*/
4679 static void genSkipz(iCode *ifx, int condition)
4680 {
4681   if(!ifx)
4682     return;
4683
4684   if(condition)
4685     emitSKPNZ;
4686   else
4687     emitSKPZ;
4688
4689   if ( IC_TRUE(ifx) )
4690     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4691   else
4692     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4693
4694   if ( IC_TRUE(ifx) )
4695     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4696   else
4697     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4698
4699 }
4700 #endif
4701
4702 #if !(USE_SIMPLE_GENCMP)
4703 /*-----------------------------------------------------------------*/
4704 /* genSkipCond                                                     */
4705 /*-----------------------------------------------------------------*/
4706 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4707 {
4708   if(!rifx)
4709     return;
4710
4711   if(rifx->condition)
4712     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4713   else
4714     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4715
4716
4717   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4718   rifx->generated = 1;
4719 }
4720 #endif
4721
4722 #if 0
4723 /*-----------------------------------------------------------------*/
4724 /* genChkZeroes :- greater or less than comparison                 */
4725 /*     For each byte in a literal that is zero, inclusive or the   */
4726 /*     the corresponding byte in the operand with W                */
4727 /*     returns true if any of the bytes are zero                   */
4728 /*-----------------------------------------------------------------*/
4729 static int genChkZeroes(operand *op, int lit,  int size)
4730 {
4731
4732   int i;
4733   int flag =1;
4734
4735   while(size--) {
4736     i = (lit >> (size*8)) & 0xff;
4737
4738     if(i==0) {
4739       if(flag) 
4740         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4741       else
4742         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4743       flag = 0;
4744     }
4745   }
4746
4747   return (flag==0);
4748 }
4749 #endif
4750
4751 #define DEBUGpc(fmt,...)  DEBUGpic16_emitcode("; =:=", "%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
4752 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
4753 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE || AOP_TYPE(x) == AOP_STA)
4754
4755 /*-----------------------------------------------------------------*/
4756 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4757 /*                  aop (if it's NOT a literal) or from lit (if    */
4758 /*                  aop is a literal)                              */
4759 /*-----------------------------------------------------------------*/
4760 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4761   if (aop->type == AOP_LIT) {
4762     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4763   } else {
4764     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4765   }
4766 }
4767
4768 /*-----------------------------------------------------------------*/
4769 /* genCmp :- greater or less than comparison                       */
4770 /*-----------------------------------------------------------------*/
4771
4772 #if USE_SIMPLE_GENCMP
4773
4774 /* genCmp performs a left < right comparison, stores
4775  * the outcome in result (if != NULL) and generates
4776  * control flow code for the ifx (if != NULL).
4777  *
4778  * This version leaves in sequences like
4779  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4780  * which should be optmized by the peephole
4781  * optimizer - RN 2005-01-01 */
4782 static void genCmp (operand *left,operand *right,
4783                     operand *result, iCode *ifx, int sign)
4784 {
4785   resolvedIfx rIfx;
4786   int size;
4787   int offs;
4788   symbol *templbl;
4789   operand *dummy;
4790   unsigned long lit;
4791   unsigned long mask;
4792   int performedLt;
4793
4794   FENTRY;
4795   
4796   assert (AOP_SIZE(left) == AOP_SIZE(right));
4797   assert (left && right);
4798
4799   size = AOP_SIZE(right) - 1;
4800   mask = (0x100UL << (size*8)) - 1;
4801   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4802   performedLt = 1;
4803   templbl = NULL;
4804   lit = 0;
4805   
4806   resolveIfx (&rIfx, ifx);
4807
4808   /**********************************************************************
4809    * handle bits - bit compares are promoted to int compares seemingly! *
4810    **********************************************************************/
4811 #if 0
4812   // THIS IS COMPLETELY UNTESTED!
4813   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4814     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4815     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4816     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4817
4818     emitSETC;
4819     // 1 < {0,1} is false --> clear C by skipping the next instruction
4820     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4821     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4822     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4823     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4824     emitCLRC; // only skipped for left=0 && right=1
4825
4826     goto correct_result_in_carry;
4827   } // if
4828 #endif
4829
4830   /*************************************************
4831    * make sure that left is register (or the like) *
4832    *************************************************/
4833   if (!isAOP_REGlike(left)) {
4834     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4835     assert (isAOP_LIT(left));
4836     assert (isAOP_REGlike(right));
4837     // swap left and right
4838     // left < right <==> right > left <==> (right >= left + 1)
4839     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4840
4841     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4842       // MAXVALUE < right? always false
4843       if (performedLt) emitCLRC; else emitSETC;
4844       goto correct_result_in_carry;
4845     } // if
4846
4847     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4848     // that's we handled it above.
4849     lit++;
4850
4851     dummy = left;
4852     left = right;
4853     right = dummy;
4854
4855     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
4856   } else if (isAOP_LIT(right)) {
4857     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4858   } // if
4859
4860   assert (isAOP_REGlike(left)); // left must be register or the like
4861   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4862
4863   /*************************************************
4864    * special cases go here                         *
4865    *************************************************/
4866
4867   if (isAOP_LIT(right)) {
4868     if (!sign) {
4869       // unsigned comparison to a literal
4870       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4871       if (lit == 0) {
4872         // unsigned left < 0? always false
4873         if (performedLt) emitCLRC; else emitSETC;
4874         goto correct_result_in_carry;
4875       }
4876     } else {
4877       // signed comparison to a literal
4878       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4879       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4880         // signed left < 0x80000000? always false
4881         if (performedLt) emitCLRC; else emitSETC;
4882         goto correct_result_in_carry;
4883       } else if (lit == 0) {
4884         // compare left < 0; set CARRY if SIGNBIT(left) is set
4885         if (performedLt) emitSETC; else emitCLRC;
4886         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4887         if (performedLt) emitCLRC; else emitSETC;
4888         goto correct_result_in_carry;
4889       }
4890     } // if (!sign)
4891   } // right is literal
4892
4893   /*************************************************
4894    * perform a general case comparison             *
4895    * make sure we get CARRY==1 <==> left >= right  *
4896    *************************************************/
4897   // compare most significant bytes
4898   //DEBUGpc ("comparing bytes at offset %d", size);
4899   if (!sign) {
4900     // unsigned comparison
4901     mov2w_regOrLit (AOP(right), lit, size);
4902     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
4903   } else {
4904     // signed comparison
4905     // (add 2^n to both operands then perform an unsigned comparison)
4906     if (isAOP_LIT(right)) {
4907       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4908       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4909
4910       if (litbyte == 0x80) {
4911         // left >= 0x80 -- always true, but more bytes to come
4912         pic16_mov2w (AOP(left), size);
4913         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
4914         emitSETC;
4915       } else {
4916         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4917         pic16_mov2w (AOP(left), size);
4918         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4919         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4920       } // if
4921     } else {
4922       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
4923       //pCodeOp *pctemp = pic16_popGetTempReg(1);
4924       pic16_mov2w (AOP(left), size);
4925       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4926       pic16_emitpcode (POC_MOVWF, pctemp);
4927       pic16_mov2w (AOP(right), size);
4928       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4929       pic16_emitpcode (POC_SUBFW, pctemp);
4930       //pic16_popReleaseTempReg(pctemp, 1);
4931     }
4932   } // if (!sign)
4933
4934   // compare remaining bytes (treat as unsigned case from above)
4935   templbl = newiTempLabel ( NULL );
4936   offs = size;
4937   while (offs--) {
4938     //DEBUGpc ("comparing bytes at offset %d", offs);
4939     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
4940     mov2w_regOrLit (AOP(right), lit, offs);
4941     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
4942   } // while (offs)
4943   pic16_emitpLabel (templbl->key);
4944   goto result_in_carry;
4945
4946 result_in_carry:
4947   
4948   /****************************************************
4949    * now CARRY contains the result of the comparison: *
4950    * SUBWF sets CARRY iff                             *
4951    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4952    * (F=left, W=right)
4953    ****************************************************/
4954
4955   if (performedLt) {
4956     if (result && AOP_TYPE(result) != AOP_CRY) {
4957       // value will be stored
4958       emitTOGC;
4959     } else {
4960       // value wil only be used in the following genSkipc()
4961       rIfx.condition ^= 1;
4962     }
4963   } // if
4964
4965 correct_result_in_carry:
4966
4967   // assign result to variable (if neccessary)
4968   if (result && AOP_TYPE(result) != AOP_CRY) {
4969     //DEBUGpc ("assign result");
4970     size = AOP_SIZE(result);
4971     while (size--) {
4972       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
4973     } // while
4974     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
4975   } // if (result)
4976
4977   // perform conditional jump
4978   // genSkipc branches to rifx->label if (rifx->condition != CARRY)
4979   if (ifx) {
4980     //DEBUGpc ("generate control flow");
4981     rIfx.condition ^= 1;
4982     genSkipc (&rIfx);
4983     ifx->generated = 1;
4984   } // if
4985 }
4986
4987 #elif 1
4988                 /* { */
4989       /* original code */
4990 static void genCmp (operand *left,operand *right,
4991                     operand *result, iCode *ifx, int sign)
4992 {
4993   int size; //, offset = 0 ;
4994   unsigned long lit = 0L,i = 0;
4995   resolvedIfx rFalseIfx;
4996   //  resolvedIfx rTrueIfx;
4997   symbol *truelbl;
4998   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4999 /*
5000   if(ifx) {
5001     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5002     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5003   }
5004 */
5005
5006   FENTRY;
5007   
5008   resolveIfx(&rFalseIfx,ifx);
5009   truelbl  = newiTempLabel(NULL);
5010   size = max(AOP_SIZE(left),AOP_SIZE(right));
5011
5012   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5013
5014 #define _swapp
5015
5016   /* if literal is on the right then swap with left */
5017   if ((AOP_TYPE(right) == AOP_LIT)) {
5018     operand *tmp = right ;
5019     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5020     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5021 #ifdef _swapp
5022
5023     lit = (lit - 1) & mask;
5024     right = left;
5025     left = tmp;
5026     rFalseIfx.condition ^= 1;
5027 #endif
5028
5029   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5030     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5031   }
5032
5033
5034   //if(IC_TRUE(ifx) == NULL)
5035   /* if left & right are bit variables */
5036   if (AOP_TYPE(left) == AOP_CRY &&
5037       AOP_TYPE(right) == AOP_CRY ) {
5038     assert (0 && "bit variables used in genCmp");
5039     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5040     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5041   } else {
5042     /* subtract right from left if at the
5043        end the carry flag is set then we know that
5044        left is greater than right */
5045
5046     symbol *lbl  = newiTempLabel(NULL);
5047
5048 #if 0
5049         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5050                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5051 #endif
5052
5053 #ifndef _swapp
5054     if(AOP_TYPE(right) == AOP_LIT) {
5055
5056       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5057
5058       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5059
5060       /* special cases */
5061
5062       if(lit == 0) {
5063
5064         if(sign != 0) 
5065           genSkipCond(&rFalseIfx,left,size-1,7);
5066         else 
5067           /* no need to compare to 0...*/
5068           /* NOTE: this is a de-generate compare that most certainly 
5069            *       creates some dead code. */
5070           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5071
5072         if(ifx) ifx->generated = 1;
5073         return;
5074
5075       }
5076       size--;
5077
5078       if(size == 0) {
5079         //i = (lit >> (size*8)) & 0xff;
5080         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5081         
5082         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5083
5084         i = ((0-lit) & 0xff);
5085         if(sign) {
5086           if( i == 0x81) { 
5087             /* lit is 0x7f, all signed chars are less than
5088              * this except for 0x7f itself */
5089             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5090             genSkipz2(&rFalseIfx,0);
5091           } else {
5092             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5093             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5094             genSkipc(&rFalseIfx);
5095           }
5096
5097         } else {
5098           if(lit == 1) {
5099             genSkipz2(&rFalseIfx,1);
5100           } else {
5101             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5102             genSkipc(&rFalseIfx);
5103           }
5104         }
5105
5106         if(ifx) ifx->generated = 1;
5107         return;
5108       }
5109
5110       /* chars are out of the way. now do ints and longs */
5111
5112
5113       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5114         
5115       /* special cases */
5116
5117       if(sign) {
5118
5119         if(lit == 0) {
5120           genSkipCond(&rFalseIfx,left,size,7);
5121           if(ifx) ifx->generated = 1;
5122           return;
5123         }
5124
5125         if(lit <0x100) {
5126           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5127
5128           //rFalseIfx.condition ^= 1;
5129           //genSkipCond(&rFalseIfx,left,size,7);
5130           //rFalseIfx.condition ^= 1;
5131
5132           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5133           if(rFalseIfx.condition)
5134             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5135           else
5136             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5137
5138           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5139           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5140           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5141
5142           while(size > 1)
5143             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5144
5145           if(rFalseIfx.condition) {
5146             emitSKPZ;
5147             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5148
5149           } else {
5150             emitSKPNZ;
5151           }
5152
5153           genSkipc(&rFalseIfx);
5154           pic16_emitpLabel(truelbl->key);
5155           if(ifx) ifx->generated = 1;
5156           return;
5157
5158         }
5159
5160         if(size == 1) {
5161
5162           if( (lit & 0xff) == 0) {
5163             /* lower byte is zero */
5164             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5165             i = ((lit >> 8) & 0xff) ^0x80;
5166             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5167             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5168             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5169             genSkipc(&rFalseIfx);
5170
5171
5172             if(ifx) ifx->generated = 1;
5173             return;
5174
5175           }
5176         } else {
5177           /* Special cases for signed longs */
5178           if( (lit & 0xffffff) == 0) {
5179             /* lower byte is zero */
5180             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5181             i = ((lit >> 8*3) & 0xff) ^0x80;
5182             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5183             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5184             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5185             genSkipc(&rFalseIfx);
5186
5187
5188             if(ifx) ifx->generated = 1;
5189             return;
5190
5191           }
5192
5193         }
5194
5195
5196         if(lit & (0x80 << (size*8))) {
5197           /* lit is negative */
5198           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5199
5200           //genSkipCond(&rFalseIfx,left,size,7);
5201
5202           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5203
5204           if(rFalseIfx.condition)
5205             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5206           else
5207             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5208
5209
5210         } else {
5211           /* lit is positive */
5212           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5213           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5214           if(rFalseIfx.condition)
5215             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5216           else
5217             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5218
5219         }
5220
5221         /*
5222           This works, but is only good for ints.
5223           It also requires a "known zero" register.
5224           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5225           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5226           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5227           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5228           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5229           genSkipc(&rFalseIfx);
5230
5231           pic16_emitpLabel(truelbl->key);
5232           if(ifx) ifx->generated = 1;
5233           return;
5234         **/
5235           
5236         /* There are no more special cases, so perform a general compare */
5237   
5238         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5239         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5240
5241         while(size--) {
5242
5243           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5244           emitSKPNZ;
5245           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5246         }
5247         //rFalseIfx.condition ^= 1;
5248         genSkipc(&rFalseIfx);
5249
5250         pic16_emitpLabel(truelbl->key);
5251
5252         if(ifx) ifx->generated = 1;
5253         return;
5254
5255
5256       }
5257
5258
5259       /* sign is out of the way. So now do an unsigned compare */
5260       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5261
5262
5263       /* General case - compare to an unsigned literal on the right.*/
5264
5265       i = (lit >> (size*8)) & 0xff;
5266       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5267       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5268       while(size--) {
5269         i = (lit >> (size*8)) & 0xff;
5270
5271         if(i) {
5272           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5273           emitSKPNZ;
5274           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5275         } else {
5276           /* this byte of the lit is zero, 
5277            *if it's not the last then OR in the variable */
5278           if(size)
5279             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5280         }
5281       }
5282
5283
5284       pic16_emitpLabel(lbl->key);
5285 //      pic16_emitpLabel(truelbl->key);
5286       //if(emitFinalCheck)
5287       genSkipc(&rFalseIfx);
5288       if(sign)
5289         pic16_emitpLabel(truelbl->key);
5290
5291       if(ifx) ifx->generated = 1;
5292       return;
5293
5294
5295     }
5296 #endif  // _swapp
5297
5298     if(AOP_TYPE(left) == AOP_LIT) {
5299       //symbol *lbl = newiTempLabel(NULL);
5300
5301       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5302
5303
5304       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5305
5306       /* Special cases */
5307       if((lit == 0) && (sign == 0)){
5308
5309         size--;
5310         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5311         while(size) 
5312           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5313
5314         genSkipz2(&rFalseIfx,0);
5315         if(ifx) ifx->generated = 1;
5316         return;
5317       }
5318
5319       if(size==1) {
5320         /* Special cases */
5321         lit &= 0xff;
5322         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5323           /* degenerate compare can never be true */
5324           if(rFalseIfx.condition == 0)
5325             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5326
5327           if(ifx) ifx->generated = 1;
5328           return;
5329         }
5330
5331         if(sign) {
5332           /* signed comparisons to a literal byte */
5333
5334           int lp1 = (lit+1) & 0xff;
5335
5336           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5337           switch (lp1) {
5338           case 0:
5339             rFalseIfx.condition ^= 1;
5340             genSkipCond(&rFalseIfx,right,0,7);
5341             break;
5342           case 0x7f:
5343             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5344             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5345             genSkipz2(&rFalseIfx,1);
5346             break;
5347           default:
5348             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5349             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5350             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5351             rFalseIfx.condition ^= 1;
5352             genSkipc(&rFalseIfx);
5353             break;
5354           }
5355         } else {
5356           /* unsigned comparisons to a literal byte */
5357
5358           switch(lit & 0xff ) {
5359           case 0:
5360             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5361             genSkipz2(&rFalseIfx,0);
5362             break;
5363           case 0x7f:
5364             rFalseIfx.condition ^= 1;
5365             genSkipCond(&rFalseIfx,right,0,7);
5366             break;
5367
5368           default:
5369             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5370             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5371             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5372             rFalseIfx.condition ^= 1;
5373             if (AOP_TYPE(result) == AOP_CRY)
5374               genSkipc(&rFalseIfx);
5375             else {
5376               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5377               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5378             }         
5379             break;
5380           }
5381         }
5382
5383         if(ifx) ifx->generated = 1;
5384         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5385                 goto check_carry;
5386         return;
5387
5388       } else {
5389
5390         /* Size is greater than 1 */
5391
5392         if(sign) {
5393           int lp1 = lit+1;
5394
5395           size--;
5396
5397           if(lp1 == 0) {
5398             /* this means lit = 0xffffffff, or -1 */
5399
5400
5401             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5402             rFalseIfx.condition ^= 1;
5403             genSkipCond(&rFalseIfx,right,size,7);
5404             if(ifx) ifx->generated = 1;
5405
5406             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5407               goto check_carry;
5408
5409             return;
5410           }
5411
5412           if(lit == 0) {
5413             int s = size;
5414
5415             if(rFalseIfx.condition) {
5416               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5417               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5418             }
5419
5420             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5421             while(size--)
5422               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5423
5424
5425             emitSKPZ;
5426             if(rFalseIfx.condition) {
5427               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5428               pic16_emitpLabel(truelbl->key);
5429             }else {
5430               rFalseIfx.condition ^= 1;
5431               genSkipCond(&rFalseIfx,right,s,7);
5432             }
5433
5434             if(ifx) ifx->generated = 1;
5435
5436             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5437               goto check_carry;
5438
5439             return;
5440           }
5441
5442           if((size == 1) &&  (0 == (lp1&0xff))) {
5443             /* lower byte of signed word is zero */
5444             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5445             i = ((lp1 >> 8) & 0xff) ^0x80;
5446             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5447             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5448             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5449
5450             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5451               emitTOGC;
5452               if(ifx) ifx->generated = 1;
5453               goto check_carry;
5454             } else {
5455               rFalseIfx.condition ^= 1;
5456               genSkipc(&rFalseIfx);
5457               if(ifx) ifx->generated = 1;
5458             }
5459
5460             return;
5461           }
5462
5463           if(lit & (0x80 << (size*8))) {
5464             /* Lit is less than zero */
5465             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5466             //rFalseIfx.condition ^= 1;
5467             //genSkipCond(&rFalseIfx,left,size,7);
5468             //rFalseIfx.condition ^= 1;
5469             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5470             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5471
5472             if(rFalseIfx.condition)
5473               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5474             else
5475               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5476
5477
5478           } else {
5479             /* Lit is greater than or equal to zero */
5480             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5481             //rFalseIfx.condition ^= 1;
5482             //genSkipCond(&rFalseIfx,right,size,7);
5483             //rFalseIfx.condition ^= 1;
5484
5485             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5486             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5487
5488             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5489             if(rFalseIfx.condition)
5490               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5491             else
5492               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5493
5494           }
5495
5496           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5497           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5498
5499           while(size--) {
5500
5501             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5502             emitSKPNZ;
5503             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5504           }
5505           rFalseIfx.condition ^= 1;
5506           //rFalseIfx.condition = 1;
5507           genSkipc(&rFalseIfx);
5508
5509           pic16_emitpLabel(truelbl->key);
5510
5511           if(ifx) ifx->generated = 1;
5512
5513
5514           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5515             goto check_carry;
5516
5517           return;
5518           // end of if (sign)
5519         } else {
5520
5521           /* compare word or long to an unsigned literal on the right.*/
5522
5523
5524           size--;
5525           if(lit < 0xff) {
5526             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5527             switch (lit) {
5528             case 0:
5529               break; /* handled above */
5530 /*
5531             case 0xff:
5532               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5533               while(size--)
5534                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5535               genSkipz2(&rFalseIfx,0);
5536               break;
5537 */
5538             default:
5539               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5540               while(--size)
5541                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5542
5543               emitSKPZ;
5544               if(rFalseIfx.condition)
5545                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5546               else
5547                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5548
5549
5550               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5551               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5552
5553               rFalseIfx.condition ^= 1;
5554               genSkipc(&rFalseIfx);
5555             }
5556
5557             pic16_emitpLabel(truelbl->key);
5558
5559             if(ifx) ifx->generated = 1;
5560
5561             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5562               goto check_carry;
5563
5564             return;
5565           }
5566
5567
5568           lit++;
5569           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5570           i = (lit >> (size*8)) & 0xff;
5571
5572           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5573           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5574
5575           while(size--) {
5576             i = (lit >> (size*8)) & 0xff;
5577
5578             if(i) {
5579               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5580               emitSKPNZ;
5581               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5582             } else {
5583               /* this byte of the lit is zero, 
5584                * if it's not the last then OR in the variable */
5585               if(size)
5586                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5587             }
5588           }
5589
5590
5591           pic16_emitpLabel(lbl->key);
5592
5593           rFalseIfx.condition ^= 1;
5594
5595           genSkipc(&rFalseIfx);
5596         }
5597
5598         if(sign)
5599           pic16_emitpLabel(truelbl->key);
5600         if(ifx) ifx->generated = 1;
5601
5602             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5603               goto check_carry;
5604
5605         return;
5606       }
5607     }
5608     /* Compare two variables */
5609
5610     DEBUGpic16_emitcode(";sign","%d",sign);
5611
5612     size--;
5613     if(sign) {
5614       /* Sigh. thus sucks... */
5615       if(size) {
5616         pCodeOp *pctemp;
5617         
5618         pctemp = pic16_popGetTempReg(1);
5619         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5620         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5621         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5622         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5623         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5624         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5625         pic16_popReleaseTempReg(pctemp, 1);
5626       } else {
5627         /* Signed char comparison */
5628         /* Special thanks to Nikolai Golovchenko for this snippet */
5629         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5630         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5631         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5632         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5633         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5634         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5635
5636         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5637         genSkipc(&rFalseIfx);
5638           
5639         if(ifx) ifx->generated = 1;
5640
5641             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5642               goto check_carry;
5643
5644         return;
5645       }
5646
5647     } else {
5648
5649       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5650       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5651     }
5652
5653
5654     /* The rest of the bytes of a multi-byte compare */
5655     while (size) {
5656
5657       emitSKPZ;
5658       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5659       size--;
5660
5661       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5662       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5663
5664
5665     }
5666
5667     pic16_emitpLabel(lbl->key);
5668
5669     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5670     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5671         (AOP_TYPE(result) == AOP_REG)) {
5672       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5673       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5674     } else {
5675       genSkipc(&rFalseIfx);
5676     }         
5677     //genSkipc(&rFalseIfx);
5678     if(ifx) ifx->generated = 1;
5679
5680
5681             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5682               goto check_carry;
5683
5684     return;
5685
5686   }
5687
5688 check_carry:
5689   if ((AOP_TYPE(result) != AOP_CRY) 
5690         && AOP_SIZE(result)) {
5691     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5692
5693     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5694
5695     pic16_outBitC(result);
5696   } else {
5697     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5698     /* if the result is used in the next
5699        ifx conditional branch then generate
5700        code a little differently */
5701     if (ifx )
5702       genIfxJump (ifx,"c");
5703     else
5704       pic16_outBitC(result);
5705     /* leave the result in acc */
5706   }
5707
5708 }
5709
5710 #else   /* old version of genCmp() */   /* } else { */
5711
5712 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5713 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5714         operand *result, int offset, int invert_op)
5715 {
5716   /* add code here */
5717   
5718   /* check condition, > or < ?? */
5719   if(rIfx->condition != 0)invert_op ^= 1;
5720   
5721   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5722
5723   if(!ifx)invert_op ^= 1;
5724
5725   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5726       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5727   
5728   /* do selection */
5729   if(!invert_op)return POC_CPFSGT;
5730   else return POC_CPFSLT;
5731 }
5732
5733 static int compareAopfirstpass=1;
5734
5735 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5736             operand *oper, int offset, operand *result,
5737             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5738             symbol *tlbl)
5739 {
5740   int op;
5741   symbol *truelbl;
5742
5743   /* invert if there is a result to be loaded, in order to fit,
5744    * SETC/CLRC sequence */
5745   if(AOP_SIZE(result))invert_op ^= 1;
5746
5747 //  if(sign && !offset)invert_op ^= 1;
5748   
5749 //  if(sign)invert_op ^= 1;
5750   
5751   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5752
5753   if(AOP_SIZE(result) && compareAopfirstpass) {
5754     if(!ifx) {
5755       if(pcop2)
5756         pic16_emitpcode(POC_SETF, pcop2);
5757       else
5758         emitSETC;
5759     } else {
5760       if(pcop2)
5761         pic16_emitpcode(POC_CLRF, pcop2);
5762       else
5763         emitCLRC;
5764     }
5765   }
5766
5767   compareAopfirstpass = 0;
5768
5769       /* there is a bug when comparing operands with size > 1,
5770        * because higher bytes can be equal and test should be performed
5771        * to the next lower byte, current algorithm, considers operands
5772        * inequal in these cases! -- VR 20041107 */
5773
5774     
5775   if(pcop)
5776     pic16_emitpcode(op, pcop);
5777   else
5778     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5779
5780
5781   if((!sign || !offset) && AOP_SIZE(result)) {
5782     if(!ifx) {
5783       if(pcop2)
5784         pic16_emitpcode(POC_CLRF, pcop2);
5785         else
5786         emitCLRC;
5787     } else {
5788       if(pcop2)
5789         pic16_emitpcode(POC_SETF, pcop2);
5790       else
5791         emitSETC;
5792     }
5793     
5794     /* don't emit final branch (offset == 0) */
5795     if(offset) {
5796
5797       if(pcop2)
5798         pic16_emitpcode(POC_RRCF, pcop2);
5799
5800       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5801     }
5802   } else {
5803     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5804       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5805             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5806
5807       truelbl = newiTempLabel( NULL );
5808       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5809       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5810         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5811       else
5812         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5813       pic16_emitpLabel(truelbl->key);
5814     } else {
5815       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5816     }
5817   }
5818 }
5819
5820
5821   
5822
5823 #if 1   /* { */
5824 static void genCmp (operand *left, operand *right,
5825                     operand *result, iCode *ifx, int sign)
5826 {
5827   int size, cmpop=1;
5828   long lit = 0L;
5829   resolvedIfx rFalseIfx;
5830   symbol *falselbl, *tlbl;
5831
5832     FENTRY;
5833     
5834     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5835
5836     resolveIfx(&rFalseIfx, ifx);
5837     size = max(AOP_SIZE(left), AOP_SIZE(right));
5838     
5839     /* if left & right are bit variables */
5840     if(AOP_TYPE(left) == AOP_CRY
5841       && AOP_TYPE(right) == AOP_CRY ) {
5842
5843         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5844         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5845         
5846         werror(W_POSSBUG2, __FILE__, __LINE__);
5847         exit(-1);
5848     }
5849     
5850     /* if literal is on the right then swap with left */
5851     if((AOP_TYPE(right) == AOP_LIT)) {
5852       operand *tmp = right ;
5853 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
5854
5855         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5856
5857 //      lit = (lit - 1) & mask;
5858         right = left;
5859         left = tmp;
5860         rFalseIfx.condition ^= 1;               /* reverse compare */
5861     } else
5862     if ((AOP_TYPE(left) == AOP_LIT)) {
5863       /* float compares are handled by support functions */
5864       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5865     }
5866
5867     /* actual comparing algorithm */
5868 //    size = AOP_SIZE( right );
5869
5870     falselbl = newiTempLabel( NULL );
5871     if(AOP_TYPE(left) == AOP_LIT) {
5872       /* compare to literal */
5873       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5874       
5875       if(sign) {
5876         pCodeOp *pct, *pct2;
5877         symbol *tlbl1;
5878
5879         /* signed compare */
5880         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5881
5882         pct = pic16_popCopyReg(&pic16_pc_prodl);
5883         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5884         tlbl = newiTempLabel( NULL );
5885         
5886         /* first compare signs:
5887          *  a. if both are positive, compare just like unsigned
5888          *  b. if both are negative, invert cmpop, compare just like unsigned
5889          *  c. if different signs, determine the result directly */
5890
5891         size--;
5892
5893 #if 1
5894         /* { */
5895         tlbl1 = newiTempLabel( NULL );
5896 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
5897
5898         if(lit > 0) {
5899
5900           /* literal is zero or positive:
5901            *  a. if carry is zero, too, continue compare,
5902            *  b. if carry is set, then continue depending on cmpop ^ condition:
5903            *    1. '<' return false (literal < variable),
5904            *    2. '>' return true (literal > variable) */
5905 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
5906           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5907           
5908           
5909           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5910           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
5911         } else 
5912         if(lit < 0) {
5913           
5914           /* literal is negative:
5915            *  a. if carry is set, too, continue compare,
5916            *  b. if carry is zero, then continue depending on cmpop ^ condition:
5917            *    1. '<' return true (literal < variable),
5918            *    2. '>' return false (literal > variable) */
5919 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
5920           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5921           
5922           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5923           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5924         }
5925 #if 1
5926         else {
5927           /* lit == 0 */
5928           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5929           
5930           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5931           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5932         }
5933 #endif
5934         
5935         
5936         pic16_emitpLabel( tlbl1->key );
5937 #endif  /* } */
5938
5939         compareAopfirstpass=1;
5940 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5941 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5942 //        pic16_emitpcode(POC_MOVWF, pct);
5943
5944 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5945         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5946 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5947         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5948
5949         /* generic case */        
5950           while( size-- ) {
5951 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5952 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
5953 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5954 //            pic16_emitpcode(POC_MOVWF, pct);
5955
5956 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5957             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
5958             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5959 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5960 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
5961           }
5962 //        }
5963         
5964         if(ifx)ifx->generated = 1;
5965
5966         if(AOP_SIZE(result)) {
5967           pic16_emitpLabel(tlbl->key);
5968           pic16_emitpLabel(falselbl->key);
5969           pic16_outBitOp( result, pct2 );
5970         } else {
5971           pic16_emitpLabel(tlbl->key);
5972         }
5973       } else {
5974
5975
5976         /* unsigned compare */      
5977         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
5978     
5979         compareAopfirstpass=1;
5980         while(size--) {
5981           
5982           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5983           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
5984
5985         }
5986
5987         if(ifx)ifx->generated = 1;
5988
5989
5990         if(AOP_SIZE(result)) {
5991           pic16_emitpLabel(falselbl->key);
5992           pic16_outBitC( result );
5993         }
5994
5995       }
5996     } else {
5997       /* compare registers */
5998       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
5999
6000
6001       if(sign) {
6002         pCodeOp *pct, *pct2;
6003         
6004         /* signed compare */
6005         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6006
6007         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6008         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6009         tlbl = newiTempLabel( NULL );
6010         
6011         compareAopfirstpass=1;
6012
6013         size--;
6014         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6015 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6016         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6017         pic16_emitpcode(POC_MOVWF, pct);
6018
6019         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6020 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6021         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6022
6023         /* WREG already holds left + 0x80 */
6024         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6025         
6026         while( size-- ) {
6027           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6028 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6029           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6030           pic16_emitpcode(POC_MOVWF, pct);
6031                 
6032           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6033 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6034           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6035
6036           /* WREG already holds left + 0x80 */
6037           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6038 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6039         }
6040         
6041         if(ifx)ifx->generated = 1;
6042
6043         if(AOP_SIZE(result)) {
6044           pic16_emitpLabel(tlbl->key);
6045           pic16_emitpLabel(falselbl->key);
6046           pic16_outBitOp( result, pct2 );
6047         } else {
6048           pic16_emitpLabel(tlbl->key);
6049         }
6050
6051       } else {
6052         /* unsigned compare */      
6053         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6054
6055         compareAopfirstpass=1;
6056         while(size--) {
6057           
6058           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6059           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6060
6061         }
6062
6063         if(ifx)ifx->generated = 1;
6064         if(AOP_SIZE(result)) {
6065
6066           pic16_emitpLabel(falselbl->key);
6067           pic16_outBitC( result );
6068         }
6069
6070       }
6071     }
6072 }
6073
6074 #else    /* } else { */
6075
6076 /* new version of genCmp -- VR 20041012 */
6077 static void genCmp (operand *left,operand *right,
6078                     operand *result, iCode *ifx, int sign)
6079 {
6080   int size; //, offset = 0 ;
6081   unsigned long lit = 0L,i = 0;
6082   resolvedIfx rFalseIfx;
6083   int willCheckCarry=0;
6084   //  resolvedIfx rTrueIfx;
6085   symbol *truelbl;
6086
6087     FENTRY;
6088   
6089   /* General concept:
6090    * subtract right from left if at the end the carry flag is set then we
6091    * know that left is greater than right */
6092             
6093   resolveIfx(&rFalseIfx,ifx);
6094   truelbl  = newiTempLabel(NULL);
6095   size = max(AOP_SIZE(left),AOP_SIZE(right));
6096
6097   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6098
6099   /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
6100    * POC_CPFSLT compare f, wreg, skip if f less then wreg */
6101   
6102
6103   /* if literal is on the right then swap with left */
6104   if ((AOP_TYPE(right) == AOP_LIT)) {
6105     operand *tmp = right ;
6106     unsigned long mask = (0x100 << (8*(size-1))) - 1;
6107
6108       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6109
6110 //      lit = (lit - 1) & mask;
6111       right = left;
6112       left = tmp;
6113       rFalseIfx.condition ^= 1;         /* reverse compare */
6114   } else
6115   if ((AOP_TYPE(left) == AOP_LIT)) {
6116     /* float compares are handled by support functions */
6117     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
6118   }
6119
6120
6121   //if(IC_TRUE(ifx) == NULL)
6122   /* if left & right are bit variables */
6123   if (AOP_TYPE(left) == AOP_CRY &&
6124       AOP_TYPE(right) == AOP_CRY ) {
6125
6126     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6127     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6128
6129   } else {
6130     symbol *lbl  = newiTempLabel(NULL);
6131
6132     if(AOP_TYPE(left) == AOP_LIT) {
6133       DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
6134
6135       if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6136         willCheckCarry = 1;
6137       else willCheckCarry = 0;
6138
6139       /* Special cases */
6140       if((lit == 0) && (sign == 0)) {
6141         /* unsigned compare to 0 */
6142         DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
6143         
6144         size--;
6145         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6146         while(size) 
6147           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
6148
6149         genSkipz2(&rFalseIfx,0);
6150         if(ifx)ifx->generated = 1;
6151         return;
6152       }
6153
6154       if(size==1) {
6155         /* Special cases */
6156         lit &= 0xff;
6157         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
6158           /* degenerate compare can never be true */
6159           if(rFalseIfx.condition == 0)
6160             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
6161
6162           if(ifx) ifx->generated = 1;
6163           return;
6164         }
6165
6166         if(sign) {
6167           /* signed comparisons to a literal byte */
6168           DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6169
6170           int lp1 = (lit+1) & 0xff;
6171
6172           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
6173           switch (lp1) {
6174           case 0:
6175             rFalseIfx.condition ^= 1;
6176             genSkipCond(&rFalseIfx,right,0,7);
6177             break;
6178           case 0x7f:
6179             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6180             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
6181             genSkipz2(&rFalseIfx,1);
6182             break;
6183           default:
6184             pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
6185             
6186             if(rFalseIfx.condition)
6187               pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
6188             else
6189               pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
6190
6191             if(willCheckCarry) {
6192               if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
6193               else { emitSETC; emitCLRC; }
6194               
6195             } else {
6196               pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6197             }              
6198                       
6199 /*          pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6200             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6201             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
6202             rFalseIfx.condition ^= 1;
6203             genSkipc(&rFalseIfx);
6204 */
6205             break;
6206           }
6207         } else {
6208           /* unsigned comparisons to a literal byte */
6209           DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6210
6211           switch(lit & 0xff ) {
6212                           /* special cases */
6213           case 0:
6214             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6215             genSkipz2(&rFalseIfx,0);
6216             break;
6217           case 0x7f:
6218             rFalseIfx.condition ^= 1;
6219             genSkipCond(&rFalseIfx,right,0,7);
6220             break;
6221           default:
6222             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
6223             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6224             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6225             rFalseIfx.condition ^= 1;
6226             if (AOP_TYPE(result) == AOP_CRY)
6227               genSkipc(&rFalseIfx);
6228             else {
6229               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6230               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6231             }         
6232             break;
6233           }
6234         }
6235
6236         if(ifx) ifx->generated = 1;
6237         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6238                 goto check_carry;
6239         return;
6240
6241       } else {
6242
6243         /* Size is greater than 1 */
6244
6245         if(sign) {
6246           int lp1 = lit+1;
6247
6248           size--;
6249
6250           if(lp1 == 0) {
6251             /* this means lit = 0xffffffff, or -1 */
6252
6253
6254             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
6255             rFalseIfx.condition ^= 1;
6256             genSkipCond(&rFalseIfx,right,size,7);
6257             if(ifx) ifx->generated = 1;
6258             return;
6259           }
6260
6261           if(lit == 0) {
6262             int s = size;
6263
6264             if(rFalseIfx.condition) {
6265               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6266               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6267             }
6268
6269             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6270             while(size--)
6271               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6272
6273
6274             emitSKPZ;
6275             if(rFalseIfx.condition) {
6276               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6277               pic16_emitpLabel(truelbl->key);
6278             }else {
6279               rFalseIfx.condition ^= 1;
6280               genSkipCond(&rFalseIfx,right,s,7);
6281             }
6282
6283             if(ifx) ifx->generated = 1;
6284             return;
6285           }
6286
6287           if((size == 1) &&  (0 == (lp1&0xff))) {
6288             /* lower byte of signed word is zero */
6289             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
6290             i = ((lp1 >> 8) & 0xff) ^0x80;
6291             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6292             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6293             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6294             rFalseIfx.condition ^= 1;
6295             genSkipc(&rFalseIfx);
6296
6297
6298             if(ifx) ifx->generated = 1;
6299             return;
6300           }
6301
6302           if(lit & (0x80 << (size*8))) {
6303             /* Lit is less than zero */
6304             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
6305             //rFalseIfx.condition ^= 1;
6306             //genSkipCond(&rFalseIfx,left,size,7);
6307             //rFalseIfx.condition ^= 1;
6308             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6309             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6310
6311             if(rFalseIfx.condition)
6312               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6313             else
6314               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6315
6316
6317           } else {
6318             /* Lit is greater than or equal to zero */
6319             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
6320             //rFalseIfx.condition ^= 1;
6321             //genSkipCond(&rFalseIfx,right,size,7);
6322             //rFalseIfx.condition ^= 1;
6323
6324             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6325             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6326
6327             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6328             if(rFalseIfx.condition)
6329               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6330             else
6331               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6332
6333           }
6334
6335
6336           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6337           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6338
6339           while(size--) {
6340
6341             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6342             emitSKPNZ;
6343             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6344           }
6345           rFalseIfx.condition ^= 1;
6346           //rFalseIfx.condition = 1;
6347           genSkipc(&rFalseIfx);
6348
6349           pic16_emitpLabel(truelbl->key);
6350
6351           if(ifx) ifx->generated = 1;
6352           return;
6353           // end of if (sign)
6354         } else {
6355
6356           /* compare word or long to an unsigned literal on the right.*/
6357
6358
6359           size--;
6360           if(lit < 0xff) {
6361             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6362             switch (lit) {
6363             case 0:
6364               break; /* handled above */
6365 /*
6366             case 0xff:
6367               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6368               while(size--)
6369                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6370               genSkipz2(&rFalseIfx,0);
6371               break;
6372 */
6373             default:
6374               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6375               while(--size)
6376                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6377
6378               emitSKPZ;
6379               if(rFalseIfx.condition)
6380                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6381               else
6382                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6383
6384
6385               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6386               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6387
6388               rFalseIfx.condition ^= 1;
6389               genSkipc(&rFalseIfx);
6390             }
6391
6392             pic16_emitpLabel(truelbl->key);
6393
6394             if(ifx) ifx->generated = 1;
6395             return;
6396           }
6397
6398
6399           lit++;
6400           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6401           i = (lit >> (size*8)) & 0xff;
6402
6403           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6404           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6405
6406           while(size--) {
6407             i = (lit >> (size*8)) & 0xff;
6408
6409             if(i) {
6410               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6411               emitSKPNZ;
6412               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6413             } else {
6414               /* this byte of the lit is zero, 
6415                * if it's not the last then OR in the variable */
6416               if(size)
6417                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6418             }
6419           }
6420
6421
6422           pic16_emitpLabel(lbl->key);
6423
6424           rFalseIfx.condition ^= 1;
6425
6426           genSkipc(&rFalseIfx);
6427         }
6428
6429         if(sign)
6430           pic16_emitpLabel(truelbl->key);
6431         if(ifx) ifx->generated = 1;
6432         return;
6433       }
6434     }
6435     /* Compare two variables */
6436
6437     DEBUGpic16_emitcode(";sign","%d",sign);
6438
6439     size--;
6440     if(sign) {
6441       /* Sigh. thus sucks... */
6442       if(size) {
6443         pCodeOp *pctemp;
6444         
6445         pctemp = pic16_popGetTempReg(1);
6446         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6447         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6448         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6449         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6450         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6451         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6452         pic16_popReleaseTempReg(pctemp, 1);
6453       } else {
6454         /* Signed char comparison */
6455         /* Special thanks to Nikolai Golovchenko for this snippet */
6456         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6457         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6458         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
6459         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6460         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6461         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6462
6463         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6464         genSkipc(&rFalseIfx);
6465           
6466         if(ifx) ifx->generated = 1;
6467         return;
6468       }
6469
6470     } else {
6471
6472       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6473       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6474     }
6475
6476
6477     /* The rest of the bytes of a multi-byte compare */
6478     while (size) {
6479
6480       emitSKPZ;
6481       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
6482       size--;
6483
6484       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6485       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6486
6487
6488     }
6489
6490     pic16_emitpLabel(lbl->key);
6491
6492     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6493     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
6494         (AOP_TYPE(result) == AOP_REG)) {
6495       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6496       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6497     } else {
6498       genSkipc(&rFalseIfx);
6499     }         
6500     //genSkipc(&rFalseIfx);
6501     if(ifx) ifx->generated = 1;
6502
6503     return;
6504
6505   }
6506
6507 check_carry:
6508   if ((AOP_TYPE(result) != AOP_CRY) 
6509         && AOP_SIZE(result)) {
6510     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6511
6512     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6513
6514     pic16_outBitC(result);
6515   } else {
6516     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6517     /* if the result is used in the next
6518        ifx conditional branch then generate
6519        code a little differently */
6520     if (ifx )
6521       genIfxJump (ifx,"c");
6522     else
6523       pic16_outBitC(result);
6524     /* leave the result in acc */
6525   }
6526
6527 }
6528 #endif  /* } */
6529
6530
6531 #endif  /* } */
6532
6533
6534
6535 /*-----------------------------------------------------------------*/
6536 /* genCmpGt :- greater than comparison                             */
6537 /*-----------------------------------------------------------------*/
6538 static void genCmpGt (iCode *ic, iCode *ifx)
6539 {
6540   operand *left, *right, *result;
6541   sym_link *letype , *retype;
6542   int sign ;
6543
6544     FENTRY;
6545     
6546     left = IC_LEFT(ic);
6547     right= IC_RIGHT(ic);
6548     result = IC_RESULT(ic);
6549
6550     letype = getSpec(operandType(left));
6551     retype =getSpec(operandType(right));
6552     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6553     /* assign the amsops */
6554     pic16_aopOp (left,ic,FALSE);
6555     pic16_aopOp (right,ic,FALSE);
6556     pic16_aopOp (result,ic,TRUE);
6557
6558     genCmp(right, left, result, ifx, sign);
6559
6560     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6561     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6562     pic16_freeAsmop(result,NULL,ic,TRUE); 
6563 }
6564
6565 /*-----------------------------------------------------------------*/
6566 /* genCmpLt - less than comparisons                                */
6567 /*-----------------------------------------------------------------*/
6568 static void genCmpLt (iCode *ic, iCode *ifx)
6569 {
6570   operand *left, *right, *result;
6571   sym_link *letype , *retype;
6572   int sign ;
6573
6574     FENTRY;
6575
6576     left = IC_LEFT(ic);
6577     right= IC_RIGHT(ic);
6578     result = IC_RESULT(ic);
6579
6580     letype = getSpec(operandType(left));
6581     retype =getSpec(operandType(right));
6582     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6583
6584     /* assign the amsops */
6585     pic16_aopOp (left,ic,FALSE);
6586     pic16_aopOp (right,ic,FALSE);
6587     pic16_aopOp (result,ic,TRUE);
6588
6589     genCmp(left, right, result, ifx, sign);
6590
6591     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6592     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6593     pic16_freeAsmop(result,NULL,ic,TRUE); 
6594 }
6595
6596 #if 0
6597 // not needed ATM
6598 // FIXME reenable literal optimisation when the pic16 port is stable
6599
6600 /*-----------------------------------------------------------------*/
6601 /* genc16bit2lit - compare a 16 bit value to a literal             */
6602 /*-----------------------------------------------------------------*/
6603 static void genc16bit2lit(operand *op, int lit, int offset)
6604 {
6605   int i;
6606
6607   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6608   if( (lit&0xff) == 0) 
6609     i=1;
6610   else
6611     i=0;
6612
6613   switch( BYTEofLONG(lit,i)) { 
6614   case 0:
6615     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6616     break;
6617   case 1:
6618     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6619     break;
6620   case 0xff:
6621     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6622     break;
6623   default:
6624     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6625     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6626   }
6627
6628   i ^= 1;
6629
6630   switch( BYTEofLONG(lit,i)) { 
6631   case 0:
6632     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6633     break;
6634   case 1:
6635     emitSKPNZ;
6636     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6637     break;
6638   case 0xff:
6639     emitSKPNZ;
6640     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6641     break;
6642   default:
6643     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6644     emitSKPNZ;
6645     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6646
6647   }
6648
6649 }
6650 #endif
6651
6652 #if 0
6653 // not needed ATM
6654 /*-----------------------------------------------------------------*/
6655 /* gencjneshort - compare and jump if not equal                    */
6656 /*-----------------------------------------------------------------*/
6657 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6658 {
6659   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6660   int offset = 0;
6661   int res_offset = 0;  /* the result may be a different size then left or right */
6662   int res_size = AOP_SIZE(result);
6663   resolvedIfx rIfx;
6664   symbol *lbl, *lbl_done;
6665
6666   unsigned long lit = 0L;
6667   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6668
6669   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6670   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6671   if(result)
6672     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6673   resolveIfx(&rIfx,ifx);
6674   lbl =  newiTempLabel(NULL);
6675   lbl_done =  newiTempLabel(NULL);
6676
6677
6678   /* if the left side is a literal or 
6679      if the right is in a pointer register and left 
6680      is not */
6681   if ((AOP_TYPE(left) == AOP_LIT) || 
6682       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6683     operand *t = right;
6684     right = left;
6685     left = t;
6686   }
6687   if(AOP_TYPE(right) == AOP_LIT)
6688     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6689
6690   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6691     preserve_result = 1;
6692
6693   if(result && !preserve_result)
6694     {
6695       int i;
6696       for(i = 0; i < AOP_SIZE(result); i++)
6697         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6698     }
6699
6700
6701   /* if the right side is a literal then anything goes */
6702   if (AOP_TYPE(right) == AOP_LIT &&
6703       AOP_TYPE(left) != AOP_DIR ) {
6704     switch(size) {
6705     case 2:
6706       genc16bit2lit(left, lit, 0);
6707       emitSKPZ;
6708       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6709       break;
6710     default:
6711       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6712       while (size--) {
6713         if(lit & 0xff) {
6714           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6715           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6716         } else {
6717           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6718         }
6719
6720         emitSKPZ;
6721         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6722         offset++;
6723         if(res_offset < res_size-1)
6724           res_offset++;
6725         lit >>= 8;
6726       }
6727       break;
6728     }
6729   }
6730
6731   /* if the right side is in a register or in direct space or
6732      if the left is a pointer register & right is not */    
6733   else if (AOP_TYPE(right) == AOP_REG ||
6734            AOP_TYPE(right) == AOP_DIR || 
6735            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6736            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6737     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6738     int lbl_key = lbl->key;
6739
6740     if(result) {
6741       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6742       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6743     }else {
6744       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6745       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6746               __FUNCTION__,__LINE__);
6747       return;
6748     }
6749    
6750 /*     switch(size) { */
6751 /*     case 2: */
6752 /*       genc16bit2lit(left, lit, 0); */
6753 /*       emitSKPNZ; */
6754 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6755 /*       break; */
6756 /*     default: */
6757     while (size--) {
6758       int emit_skip=1;
6759       if((AOP_TYPE(left) == AOP_DIR) && 
6760          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6761
6762         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6763         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6764
6765       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6766             
6767         switch (lit & 0xff) {
6768         case 0:
6769           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6770           break;
6771         case 1:
6772           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6773           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6774           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6775           emit_skip=0;
6776           break;
6777         case 0xff:
6778           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6779           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6780           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6781           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6782           emit_skip=0;
6783           break;
6784         default:
6785           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6786           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6787         }
6788         lit >>= 8;
6789
6790       } else {
6791         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6792       }
6793       if(emit_skip) {
6794         if(AOP_TYPE(result) == AOP_CRY) {
6795           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6796           if(rIfx.condition)
6797             emitSKPNZ;
6798           else
6799             emitSKPZ;
6800           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6801         } else {
6802           /* fix me. probably need to check result size too */
6803           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6804           if(rIfx.condition)
6805             emitSKPZ;
6806           else
6807             emitSKPNZ;
6808           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6809           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6810         }
6811         if(ifx)
6812           ifx->generated=1;
6813       }
6814       emit_skip++;
6815       offset++;
6816       if(res_offset < res_size-1)
6817         res_offset++;
6818     }
6819 /*       break; */
6820 /*     } */
6821   } else if(AOP_TYPE(right) == AOP_REG &&
6822             AOP_TYPE(left) != AOP_DIR){
6823
6824     while(size--) {
6825       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6826       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6827       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6828       if(rIfx.condition)
6829         emitSKPNZ;
6830       else
6831         emitSKPZ;
6832       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6833       offset++;
6834       if(res_offset < res_size-1)
6835         res_offset++;
6836     }
6837       
6838   }else{
6839     /* right is a pointer reg need both a & b */
6840     while(size--) {
6841       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6842       if(strcmp(l,"b"))
6843         pic16_emitcode("mov","b,%s",l);
6844       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6845       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6846       offset++;
6847     }
6848   }
6849
6850   if(result && preserve_result)
6851     {
6852       int i;
6853       for(i = 0; i < AOP_SIZE(result); i++)
6854         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6855     }
6856
6857   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6858
6859   if(result && preserve_result)
6860     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6861
6862   if(!rIfx.condition)
6863     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6864
6865   pic16_emitpLabel(lbl->key);
6866
6867   if(result && preserve_result)
6868     {
6869       int i;
6870       for(i = 0; i < AOP_SIZE(result); i++)
6871         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6872
6873       pic16_emitpLabel(lbl_done->key);
6874    }
6875
6876   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6877
6878   if(ifx)
6879     ifx->generated = 1;
6880 }
6881 #endif
6882
6883 #if 0
6884 /*-----------------------------------------------------------------*/
6885 /* gencjne - compare and jump if not equal                         */
6886 /*-----------------------------------------------------------------*/
6887 static void gencjne(operand *left, operand *right, iCode *ifx)
6888 {
6889     symbol *tlbl  = newiTempLabel(NULL);
6890
6891     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6892     gencjneshort(left, right, lbl);
6893
6894     pic16_emitcode("mov","a,%s",one);
6895     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6896     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6897     pic16_emitcode("clr","a");
6898     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6899
6900     pic16_emitpLabel(lbl->key);
6901     pic16_emitpLabel(tlbl->key);
6902
6903 }
6904 #endif
6905
6906
6907 /*-----------------------------------------------------------------*/
6908 /* is_LitOp - check if operand has to be treated as literal        */
6909 /*-----------------------------------------------------------------*/
6910 static bool is_LitOp(operand *op)
6911 {
6912   return ((AOP_TYPE(op) == AOP_LIT)
6913       || ( (AOP_TYPE(op) == AOP_PCODE)
6914           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6915               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6916 }
6917
6918 /*-----------------------------------------------------------------*/
6919 /* is_LitAOp - check if operand has to be treated as literal        */
6920 /*-----------------------------------------------------------------*/
6921 static bool is_LitAOp(asmop *aop)
6922 {
6923   return ((aop->type == AOP_LIT)
6924       || ( (aop->type == AOP_PCODE)
6925           && ( (aop->aopu.pcop->type == PO_LITERAL)
6926               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6927 }
6928
6929
6930
6931 /*-----------------------------------------------------------------*/
6932 /* genCmpEq - generates code for equal to                          */
6933 /*-----------------------------------------------------------------*/
6934 static void genCmpEq (iCode *ic, iCode *ifx)
6935 {
6936   operand *left, *right, *result;
6937   symbol *falselbl = newiTempLabel(NULL);
6938   symbol *donelbl = newiTempLabel(NULL);
6939
6940   int preserve_result = 0;
6941   int generate_result = 0;
6942   int i=0;
6943
6944   FENTRY;
6945   
6946   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6947   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6948   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6949  
6950   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6951
6952   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6953     {
6954       werror(W_POSSBUG2, __FILE__, __LINE__);
6955       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6956       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6957       goto release;
6958     }
6959
6960   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6961     {
6962       operand *tmp = right ;
6963       right = left;
6964       left = tmp;
6965     }
6966
6967   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6968     preserve_result = 1;
6969
6970   if(result && AOP_SIZE(result))
6971     generate_result = 1;
6972
6973   if(generate_result && !preserve_result)
6974     {
6975       for(i = 0; i < AOP_SIZE(result); i++)
6976         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6977     }
6978
6979   for(i=0; i < AOP_SIZE(left); i++)
6980     {
6981       if(AOP_TYPE(left) != AOP_ACC)
6982         {
6983           if(is_LitOp(left))
6984             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6985           else
6986             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6987         }
6988       if(is_LitOp(right))
6989         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6990       else
6991         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6992
6993       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6994     }
6995
6996   // result == true
6997
6998   if(generate_result && preserve_result)
6999     {
7000       for(i = 0; i < AOP_SIZE(result); i++)
7001         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7002     }
7003
7004   if(generate_result)
7005     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7006
7007   if(generate_result && preserve_result)
7008     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7009
7010   if(ifx && IC_TRUE(ifx))
7011     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7012
7013   if(ifx && IC_FALSE(ifx))
7014     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7015
7016   pic16_emitpLabel(falselbl->key);
7017
7018   // result == false
7019
7020   if(ifx && IC_FALSE(ifx))
7021     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7022
7023   if(generate_result && preserve_result)
7024     {
7025       for(i = 0; i < AOP_SIZE(result); i++)
7026         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7027     }
7028
7029   pic16_emitpLabel(donelbl->key);
7030
7031   if(ifx)
7032     ifx->generated = 1;
7033
7034 release:
7035   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7036   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7037   pic16_freeAsmop(result,NULL,ic,TRUE);
7038
7039 }
7040
7041
7042 #if 0
7043 // old version kept for reference
7044
7045 /*-----------------------------------------------------------------*/
7046 /* genCmpEq - generates code for equal to                          */
7047 /*-----------------------------------------------------------------*/
7048 static void genCmpEq (iCode *ic, iCode *ifx)
7049 {
7050     operand *left, *right, *result;
7051     unsigned long lit = 0L;
7052     int size,offset=0;
7053     symbol *falselbl  = newiTempLabel(NULL);
7054
7055
7056     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7057
7058     if(ifx)
7059       DEBUGpic16_emitcode ("; ifx is non-null","");
7060     else
7061       DEBUGpic16_emitcode ("; ifx is null","");
7062
7063     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7064     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7065     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7066
7067     size = max(AOP_SIZE(left),AOP_SIZE(right));
7068
7069     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7070
7071     /* if literal, literal on the right or 
7072     if the right is in a pointer register and left 
7073     is not */
7074     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
7075         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7076       operand *tmp = right ;
7077       right = left;
7078       left = tmp;
7079     }
7080
7081
7082     if(ifx && !AOP_SIZE(result)){
7083         symbol *tlbl;
7084         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
7085         /* if they are both bit variables */
7086         if (AOP_TYPE(left) == AOP_CRY &&
7087             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7088                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
7089             if(AOP_TYPE(right) == AOP_LIT){
7090                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7091                 if(lit == 0L){
7092                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7093                     pic16_emitcode("cpl","c");
7094                 } else if(lit == 1L) {
7095                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7096                 } else {
7097                     pic16_emitcode("clr","c");
7098                 }
7099                 /* AOP_TYPE(right) == AOP_CRY */
7100             } else {
7101                 symbol *lbl = newiTempLabel(NULL);
7102                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7103                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7104                 pic16_emitcode("cpl","c");
7105                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7106             }
7107             /* if true label then we jump if condition
7108             supplied is true */
7109             tlbl = newiTempLabel(NULL);
7110             if ( IC_TRUE(ifx) ) {
7111                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7112                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7113             } else {
7114                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7115                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7116             }
7117             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7118
7119                 {
7120                 /* left and right are both bit variables, result is carry */
7121                         resolvedIfx rIfx;
7122               
7123                         resolveIfx(&rIfx,ifx);
7124
7125                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7126                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7127                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7128                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7129                         genSkipz2(&rIfx,0);
7130                 }
7131         } else {
7132
7133                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
7134
7135                         /* They're not both bit variables. Is the right a literal? */
7136                         if(AOP_TYPE(right) == AOP_LIT) {
7137                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7138             
7139                         switch(size) {
7140
7141                                 case 1:
7142                                         switch(lit & 0xff) {
7143                                                 case 1:
7144                                                                 if ( IC_TRUE(ifx) ) {
7145                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7146                                                                         emitSKPNZ;
7147                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7148                                                                 } else {
7149                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7150                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7151                                                                 }
7152                                                                 break;
7153                                                 case 0xff:
7154                                                                 if ( IC_TRUE(ifx) ) {
7155                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7156                                                                         emitSKPNZ;
7157                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7158                                                                 } else {
7159                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7160                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7161                                                                 }
7162                                                                 break;
7163                                                 default:
7164                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7165                                                                 if(lit)
7166                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7167                                                                 genSkip(ifx,'z');
7168                                         } // switch lit
7169
7170
7171                                         /* end of size == 1 */
7172                                         break;
7173               
7174                                 case 2:
7175                                         genc16bit2lit(left,lit,offset);
7176                                         genSkip(ifx,'z');
7177                                         break;
7178                                         /* end of size == 2 */
7179
7180                                 default:
7181                                         /* size is 4 */
7182                                         if(lit==0) {
7183                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7184                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7185                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7186                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7187                                                 genSkip(ifx,'z');
7188                                         } else {
7189                                                 /* search for patterns that can be optimized */
7190
7191                                                 genc16bit2lit(left,lit,0);
7192                                                 lit >>= 16;
7193                                                 if(lit) {
7194                                                                 if(IC_TRUE(ifx))
7195                                                                 emitSKPZ; // if hi word unequal
7196                                                                 else
7197                                                                 emitSKPNZ; // if hi word equal
7198                                                                 // fail early
7199                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7200                                                         genc16bit2lit(left,lit,2);
7201                                                         genSkip(ifx,'z');
7202                                                 } else {
7203                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7204                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7205                                                         genSkip(ifx,'z');
7206                                                 }
7207                                         }
7208                                                 pic16_emitpLabel(falselbl->key);
7209                                                 break;
7210
7211                         } // switch size
7212           
7213                         ifx->generated = 1;
7214                         goto release ;
7215             
7216
7217           } else if(AOP_TYPE(right) == AOP_CRY ) {
7218             /* we know the left is not a bit, but that the right is */
7219             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7220             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7221                       pic16_popGet(AOP(right),offset));
7222             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7223
7224             /* if the two are equal, then W will be 0 and the Z bit is set
7225              * we could test Z now, or go ahead and check the high order bytes if
7226              * the variable we're comparing is larger than a byte. */
7227
7228             while(--size)
7229               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7230
7231             if ( IC_TRUE(ifx) ) {
7232               emitSKPNZ;
7233               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7234               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7235             } else {
7236               emitSKPZ;
7237               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7238               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7239             }
7240
7241           } else {
7242             /* They're both variables that are larger than bits */
7243             int s = size;
7244
7245             tlbl = newiTempLabel(NULL);
7246
7247             while(size--) {
7248               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7249               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7250
7251               if ( IC_TRUE(ifx) ) {
7252                 if(size) {
7253                   emitSKPZ;
7254                 
7255                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7256
7257                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7258                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7259                 } else {
7260                   emitSKPNZ;
7261
7262                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7263
7264
7265                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7266                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7267                 }
7268               } else {
7269                 emitSKPZ;
7270
7271                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7272
7273                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7274                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7275               }
7276               offset++;
7277             }
7278             if(s>1 && IC_TRUE(ifx)) {
7279               pic16_emitpLabel(tlbl->key);
7280               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7281             }
7282           }
7283         }
7284         /* mark the icode as generated */
7285         ifx->generated = 1;
7286         goto release ;
7287     }
7288
7289     /* if they are both bit variables */
7290     if (AOP_TYPE(left) == AOP_CRY &&
7291         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7292         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7293         if(AOP_TYPE(right) == AOP_LIT){
7294             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7295             if(lit == 0L){
7296                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7297                 pic16_emitcode("cpl","c");
7298             } else if(lit == 1L) {
7299                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7300             } else {
7301                 pic16_emitcode("clr","c");
7302             }
7303             /* AOP_TYPE(right) == AOP_CRY */
7304         } else {
7305             symbol *lbl = newiTempLabel(NULL);
7306             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7307             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7308             pic16_emitcode("cpl","c");
7309             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7310         }
7311         /* c = 1 if egal */
7312         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7313             pic16_outBitC(result);
7314             goto release ;
7315         }
7316         if (ifx) {
7317             genIfxJump (ifx,"c");
7318             goto release ;
7319         }
7320         /* if the result is used in an arithmetic operation
7321         then put the result in place */
7322         pic16_outBitC(result);
7323     } else {
7324       
7325       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7326       gencjne(left,right,result,ifx);
7327 /*
7328       if(ifx) 
7329         gencjne(left,right,newiTempLabel(NULL));
7330       else {
7331         if(IC_TRUE(ifx)->key)
7332           gencjne(left,right,IC_TRUE(ifx)->key);
7333         else
7334           gencjne(left,right,IC_FALSE(ifx)->key);
7335         ifx->generated = 1;
7336         goto release ;
7337       }
7338       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7339         pic16_aopPut(AOP(result),"a",0);
7340         goto release ;
7341       }
7342
7343       if (ifx) {
7344         genIfxJump (ifx,"a");
7345         goto release ;
7346       }
7347 */
7348       /* if the result is used in an arithmetic operation
7349          then put the result in place */
7350 /*
7351       if (AOP_TYPE(result) != AOP_CRY) 
7352         pic16_outAcc(result);
7353 */
7354       /* leave the result in acc */
7355     }
7356
7357 release:
7358     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7359     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7360     pic16_freeAsmop(result,NULL,ic,TRUE);
7361 }
7362 #endif
7363
7364 /*-----------------------------------------------------------------*/
7365 /* ifxForOp - returns the icode containing the ifx for operand     */
7366 /*-----------------------------------------------------------------*/
7367 static iCode *ifxForOp ( operand *op, iCode *ic )
7368 {
7369   FENTRY2;
7370
7371     /* if true symbol then needs to be assigned */
7372     if (IS_TRUE_SYMOP(op))
7373         return NULL ;
7374
7375     /* if this has register type condition and
7376     the next instruction is ifx with the same operand
7377     and live to of the operand is upto the ifx only then */
7378     if (ic->next
7379         && ic->next->op == IFX
7380         && IC_COND(ic->next)->key == op->key
7381         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7382         ) {
7383                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7384           return ic->next;
7385     }
7386
7387     /*
7388     if (ic->next &&
7389         ic->next->op == IFX &&
7390         IC_COND(ic->next)->key == op->key) {
7391       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7392       return ic->next;
7393     }
7394     */
7395
7396     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7397     if (ic->next &&
7398         ic->next->op == IFX)
7399       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7400
7401     if (ic->next &&
7402         ic->next->op == IFX &&
7403         IC_COND(ic->next)->key == op->key) {
7404       DEBUGpic16_emitcode ("; "," key is okay");
7405       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7406                            OP_SYMBOL(op)->liveTo,
7407                            ic->next->seq);
7408     }
7409
7410 #if 0
7411     /* the code below is completely untested
7412      * it just allows ulong2fs.c compile -- VR */
7413          
7414     ic = ic->next;
7415     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7416                                         __FILE__, __FUNCTION__, __LINE__);
7417         
7418     /* if this has register type condition and
7419     the next instruction is ifx with the same operand
7420     and live to of the operand is upto the ifx only then */
7421     if (ic->next &&
7422         ic->next->op == IFX &&
7423         IC_COND(ic->next)->key == op->key &&
7424         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7425         return ic->next;
7426
7427     if (ic->next &&
7428         ic->next->op == IFX &&
7429         IC_COND(ic->next)->key == op->key) {
7430       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7431       return ic->next;
7432     }
7433
7434     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7435                                         __FILE__, __FUNCTION__, __LINE__);
7436
7437 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7438 #endif
7439
7440     return NULL;
7441 }
7442 /*-----------------------------------------------------------------*/
7443 /* genAndOp - for && operation                                     */
7444 /*-----------------------------------------------------------------*/
7445 static void genAndOp (iCode *ic)
7446 {
7447   operand *left,*right, *result;
7448 /*     symbol *tlbl; */
7449
7450     FENTRY;
7451
7452     /* note here that && operations that are in an
7453     if statement are taken away by backPatchLabels
7454     only those used in arthmetic operations remain */
7455     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7456     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7457     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7458
7459     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7460
7461     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7462     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7463     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7464
7465     /* if both are bit variables */
7466 /*     if (AOP_TYPE(left) == AOP_CRY && */
7467 /*         AOP_TYPE(right) == AOP_CRY ) { */
7468 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7469 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7470 /*         pic16_outBitC(result); */
7471 /*     } else { */
7472 /*         tlbl = newiTempLabel(NULL); */
7473 /*         pic16_toBoolean(left);     */
7474 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7475 /*         pic16_toBoolean(right); */
7476 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7477 /*         pic16_outBitAcc(result); */
7478 /*     } */
7479
7480     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7481     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7482     pic16_freeAsmop(result,NULL,ic,TRUE);
7483 }
7484
7485
7486 /*-----------------------------------------------------------------*/
7487 /* genOrOp - for || operation                                      */
7488 /*-----------------------------------------------------------------*/
7489 /*
7490   tsd pic port -
7491   modified this code, but it doesn't appear to ever get called
7492 */
7493
7494 static void genOrOp (iCode *ic)
7495 {
7496   operand *left,*right, *result;
7497   symbol *tlbl;
7498
7499     FENTRY;  
7500
7501   /* note here that || operations that are in an
7502     if statement are taken away by backPatchLabels
7503     only those used in arthmetic operations remain */
7504     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7505     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7506     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7507
7508     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7509
7510     /* if both are bit variables */
7511     if (AOP_TYPE(left) == AOP_CRY &&
7512         AOP_TYPE(right) == AOP_CRY ) {
7513       pic16_emitcode("clrc","");
7514       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7515                AOP(left)->aopu.aop_dir,
7516                AOP(left)->aopu.aop_dir);
7517       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7518                AOP(right)->aopu.aop_dir,
7519                AOP(right)->aopu.aop_dir);
7520       pic16_emitcode("setc","");
7521
7522     } else {
7523         tlbl = newiTempLabel(NULL);
7524         pic16_toBoolean(left);
7525         emitSKPZ;
7526         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7527         pic16_toBoolean(right);
7528         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7529
7530         pic16_outBitAcc(result);
7531     }
7532
7533     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7534     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7535     pic16_freeAsmop(result,NULL,ic,TRUE);            
7536 }
7537
7538 /*-----------------------------------------------------------------*/
7539 /* isLiteralBit - test if lit == 2^n                               */
7540 /*-----------------------------------------------------------------*/
7541 static int isLiteralBit(unsigned long lit)
7542 {
7543     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7544     0x100L,0x200L,0x400L,0x800L,
7545     0x1000L,0x2000L,0x4000L,0x8000L,
7546     0x10000L,0x20000L,0x40000L,0x80000L,
7547     0x100000L,0x200000L,0x400000L,0x800000L,
7548     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7549     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7550     int idx;
7551     
7552     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7553     for(idx = 0; idx < 32; idx++)
7554         if(lit == pw[idx])
7555             return idx+1;
7556     return 0;
7557 }
7558
7559 /*-----------------------------------------------------------------*/
7560 /* continueIfTrue -                                                */
7561 /*-----------------------------------------------------------------*/
7562 static void continueIfTrue (iCode *ic)
7563 {
7564   FENTRY;
7565   if(IC_TRUE(ic))
7566     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7567   ic->generated = 1;
7568 }
7569
7570 /*-----------------------------------------------------------------*/
7571 /* jmpIfTrue -                                                     */
7572 /*-----------------------------------------------------------------*/
7573 static void jumpIfTrue (iCode *ic)
7574 {
7575   FENTRY;
7576   if(!IC_TRUE(ic))
7577     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7578   ic->generated = 1;
7579 }
7580
7581 /*-----------------------------------------------------------------*/
7582 /* jmpTrueOrFalse -                                                */
7583 /*-----------------------------------------------------------------*/
7584 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7585 {
7586   // ugly but optimized by peephole
7587   FENTRY;
7588   if(IC_TRUE(ic)){
7589     symbol *nlbl = newiTempLabel(NULL);
7590       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7591       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7592       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7593       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7594   } else {
7595     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7596     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7597   }
7598   ic->generated = 1;
7599 }
7600
7601 /*-----------------------------------------------------------------*/
7602 /* genAnd  - code for and                                          */
7603 /*-----------------------------------------------------------------*/
7604 static void genAnd (iCode *ic, iCode *ifx)
7605 {
7606   operand *left, *right, *result;
7607   int size, offset=0;  
7608   unsigned long lit = 0L;
7609   int bytelit = 0;
7610   resolvedIfx rIfx;
7611
7612     FENTRY;
7613     
7614   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7615   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7616   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7617
7618   resolveIfx(&rIfx,ifx);
7619
7620   /* if left is a literal & right is not then exchange them */
7621   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7622       AOP_NEEDSACC(left)) {
7623     operand *tmp = right ;
7624     right = left;
7625     left = tmp;
7626   }
7627
7628   /* if result = right then exchange them */
7629   if(pic16_sameRegs(AOP(result),AOP(right))){
7630     operand *tmp = right ;
7631     right = left;
7632     left = tmp;
7633   }
7634
7635   /* if right is bit then exchange them */
7636   if (AOP_TYPE(right) == AOP_CRY &&
7637       AOP_TYPE(left) != AOP_CRY){
7638     operand *tmp = right ;
7639     right = left;
7640     left = tmp;
7641   }
7642   if(AOP_TYPE(right) == AOP_LIT)
7643     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7644
7645   size = AOP_SIZE(result);
7646
7647   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7648
7649   // if(bit & yy)
7650   // result = bit & yy;
7651   if (AOP_TYPE(left) == AOP_CRY){
7652     // c = bit & literal;
7653     if(AOP_TYPE(right) == AOP_LIT){
7654       if(lit & 1) {
7655         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7656           // no change
7657           goto release;
7658         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7659       } else {
7660         // bit(result) = 0;
7661         if(size && (AOP_TYPE(result) == AOP_CRY)){
7662           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7663           goto release;
7664         }
7665         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7666           jumpIfTrue(ifx);
7667           goto release;
7668         }
7669         pic16_emitcode("clr","c");
7670       }
7671     } else {
7672       if (AOP_TYPE(right) == AOP_CRY){
7673         // c = bit & bit;
7674         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7675         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7676       } else {
7677         // c = bit & val;
7678         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7679         // c = lsb
7680         pic16_emitcode("rrc","a");
7681         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7682       }
7683     }
7684     // bit = c
7685     // val = c
7686     if(size)
7687       pic16_outBitC(result);
7688     // if(bit & ...)
7689     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7690       genIfxJump(ifx, "c");           
7691     goto release ;
7692   }
7693
7694   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7695   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7696   if((AOP_TYPE(right) == AOP_LIT) &&
7697      (AOP_TYPE(result) == AOP_CRY) &&
7698      (AOP_TYPE(left) != AOP_CRY)){
7699     int posbit = isLiteralBit(lit);
7700     /* left &  2^n */
7701     if(posbit){
7702       posbit--;
7703       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7704       // bit = left & 2^n
7705       if(size)
7706         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7707       // if(left &  2^n)
7708       else{
7709         if(ifx){
7710 /*
7711           if(IC_TRUE(ifx)) {
7712             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7713             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7714           } else {
7715             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7716             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7717           }
7718 */
7719         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7720         size = AOP_SIZE(left);
7721
7722         {
7723           int bp = posbit, ofs=0;
7724           
7725             while(bp > 7) {
7726               bp -= 8;
7727               ofs++;
7728             }
7729         
7730           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7731                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7732
7733         }
7734 /*
7735           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7736                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7737 */
7738           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7739           
7740           ifx->generated = 1;
7741         }
7742         goto release;
7743       }
7744     } else {
7745       symbol *tlbl = newiTempLabel(NULL);
7746       int sizel = AOP_SIZE(left);
7747
7748       if(size)
7749         emitSETC;
7750
7751       while(sizel--) {
7752         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7753
7754           /* patch provided by Aaron Colwell */
7755           if((posbit = isLiteralBit(bytelit)) != 0) {
7756               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7757                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7758                                                 (posbit-1),0, PO_GPR_REGISTER));
7759
7760               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7761 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7762           } else {
7763               if (bytelit == 0xff) {
7764                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7765                    * a peephole could optimize it out -- VR */
7766                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7767               } else {
7768                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7769                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7770               }
7771
7772               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7773                             pic16_popGetLabel(tlbl->key));
7774           }
7775         
7776 #if 0
7777           /* old code, left here for reference -- VR 09/2004 */
7778           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7779           // byte ==  2^n ?
7780           if((posbit = isLiteralBit(bytelit)) != 0)
7781             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7782           else{
7783             if(bytelit != 0x0FFL)
7784               pic16_emitcode("anl","a,%s",
7785                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7786             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7787           }
7788 #endif
7789         }
7790         offset++;
7791       }
7792       // bit = left & literal
7793       if(size) {
7794         emitCLRC;
7795         pic16_emitpLabel(tlbl->key);
7796       }
7797       // if(left & literal)
7798       else {
7799         if(ifx) {
7800           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7801           ifx->generated = 1;
7802         }
7803         pic16_emitpLabel(tlbl->key);
7804         goto release;
7805       }
7806     }
7807
7808     pic16_outBitC(result);
7809     goto release ;
7810   }
7811
7812   /* if left is same as result */
7813   if(pic16_sameRegs(AOP(result),AOP(left))){
7814     int know_W = -1;
7815     for(;size--; offset++,lit>>=8) {
7816       if(AOP_TYPE(right) == AOP_LIT){
7817         switch(lit & 0xff) {
7818         case 0x00:
7819           /*  and'ing with 0 has clears the result */
7820 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7821           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7822           break;
7823         case 0xff:
7824           /* and'ing with 0xff is a nop when the result and left are the same */
7825           break;
7826
7827         default:
7828           {
7829             int p = pic16_my_powof2( (~lit) & 0xff );
7830             if(p>=0) {
7831               /* only one bit is set in the literal, so use a bcf instruction */
7832 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7833               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7834
7835             } else {
7836               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7837               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7838               if(know_W != (lit&0xff))
7839                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7840               know_W = lit &0xff;
7841               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7842             }
7843           }    
7844         }
7845       } else {
7846         if (AOP_TYPE(left) == AOP_ACC) {
7847           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7848         } else {                    
7849           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7850           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7851
7852         }
7853       }
7854     }
7855
7856   } else {
7857     // left & result in different registers
7858     if(AOP_TYPE(result) == AOP_CRY){
7859       // result = bit
7860       // if(size), result in bit
7861       // if(!size && ifx), conditional oper: if(left & right)
7862       symbol *tlbl = newiTempLabel(NULL);
7863       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7864       if(size)
7865         pic16_emitcode("setb","c");
7866       while(sizer--){
7867         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7868         pic16_emitcode("anl","a,%s",
7869                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7870         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7871         offset++;
7872       }
7873       if(size){
7874         CLRC;
7875         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7876         pic16_outBitC(result);
7877       } else if(ifx)
7878         jmpTrueOrFalse(ifx, tlbl);
7879     } else {
7880       for(;(size--);offset++) {
7881         // normal case
7882         // result = left & right
7883         if(AOP_TYPE(right) == AOP_LIT){
7884           int t = (lit >> (offset*8)) & 0x0FFL;
7885           switch(t) { 
7886           case 0x00:
7887             pic16_emitcode("clrf","%s",
7888                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7889             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7890             break;
7891           case 0xff:
7892             pic16_emitcode("movf","%s,w",
7893                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7894             pic16_emitcode("movwf","%s",
7895                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7896             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7897             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7898             break;
7899           default:
7900             pic16_emitcode("movlw","0x%x",t);
7901             pic16_emitcode("andwf","%s,w",
7902                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7903             pic16_emitcode("movwf","%s",
7904                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7905               
7906             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7907             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7908             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7909           }
7910           continue;
7911         }
7912
7913         if (AOP_TYPE(left) == AOP_ACC) {
7914           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7915           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7916         } else {
7917           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7918           pic16_emitcode("andwf","%s,w",
7919                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7920           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7921           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7922         }
7923         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7924         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7925       }
7926     }
7927   }
7928
7929   release :
7930     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7931   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7932   pic16_freeAsmop(result,NULL,ic,TRUE);     
7933 }
7934
7935 /*-----------------------------------------------------------------*/
7936 /* genOr  - code for or                                            */
7937 /*-----------------------------------------------------------------*/
7938 static void genOr (iCode *ic, iCode *ifx)
7939 {
7940     operand *left, *right, *result;
7941     int size, offset=0;
7942     unsigned long lit = 0L;
7943
7944     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7945
7946     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7947     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7948     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7949
7950     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7951
7952     /* if left is a literal & right is not then exchange them */
7953     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7954         AOP_NEEDSACC(left)) {
7955         operand *tmp = right ;
7956         right = left;
7957         left = tmp;
7958     }
7959
7960     /* if result = right then exchange them */
7961     if(pic16_sameRegs(AOP(result),AOP(right))){
7962         operand *tmp = right ;
7963         right = left;
7964         left = tmp;
7965     }
7966
7967     /* if right is bit then exchange them */
7968     if (AOP_TYPE(right) == AOP_CRY &&
7969         AOP_TYPE(left) != AOP_CRY){
7970         operand *tmp = right ;
7971         right = left;
7972         left = tmp;
7973     }
7974
7975     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7976
7977     if(AOP_TYPE(right) == AOP_LIT)
7978         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7979
7980     size = AOP_SIZE(result);
7981
7982     // if(bit | yy)
7983     // xx = bit | yy;
7984     if (AOP_TYPE(left) == AOP_CRY){
7985         if(AOP_TYPE(right) == AOP_LIT){
7986             // c = bit & literal;
7987             if(lit){
7988                 // lit != 0 => result = 1
7989                 if(AOP_TYPE(result) == AOP_CRY){
7990                   if(size)
7991                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7992                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7993                   //     AOP(result)->aopu.aop_dir,
7994                   //     AOP(result)->aopu.aop_dir);
7995                     else if(ifx)
7996                         continueIfTrue(ifx);
7997                     goto release;
7998                 }
7999             } else {
8000                 // lit == 0 => result = left
8001                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8002                     goto release;
8003                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8004             }
8005         } else {
8006             if (AOP_TYPE(right) == AOP_CRY){
8007               if(pic16_sameRegs(AOP(result),AOP(left))){
8008                 // c = bit | bit;
8009                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8010                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8011                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8012
8013                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8014                          AOP(result)->aopu.aop_dir,
8015                          AOP(result)->aopu.aop_dir);
8016                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8017                          AOP(right)->aopu.aop_dir,
8018                          AOP(right)->aopu.aop_dir);
8019                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8020                          AOP(result)->aopu.aop_dir,
8021                          AOP(result)->aopu.aop_dir);
8022               } else {
8023                 if( AOP_TYPE(result) == AOP_ACC) {
8024                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8025                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8026                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8027                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8028
8029                 } else {
8030
8031                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8032                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8033                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8034                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8035
8036                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8037                                  AOP(result)->aopu.aop_dir,
8038                                  AOP(result)->aopu.aop_dir);
8039                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8040                                  AOP(right)->aopu.aop_dir,
8041                                  AOP(right)->aopu.aop_dir);
8042                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8043                                  AOP(left)->aopu.aop_dir,
8044                                  AOP(left)->aopu.aop_dir);
8045                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8046                                  AOP(result)->aopu.aop_dir,
8047                                  AOP(result)->aopu.aop_dir);
8048                 }
8049               }
8050             } else {
8051                 // c = bit | val;
8052                 symbol *tlbl = newiTempLabel(NULL);
8053                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8054
8055
8056                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8057                 if( AOP_TYPE(right) == AOP_ACC) {
8058                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8059                   emitSKPNZ;
8060                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8061                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8062                 }
8063
8064
8065
8066                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8067                     pic16_emitcode(";XXX setb","c");
8068                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8069                          AOP(left)->aopu.aop_dir,tlbl->key+100);
8070                 pic16_toBoolean(right);
8071                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8072                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8073                     jmpTrueOrFalse(ifx, tlbl);
8074                     goto release;
8075                 } else {
8076                     CLRC;
8077                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8078                 }
8079             }
8080         }
8081         // bit = c
8082         // val = c
8083         if(size)
8084             pic16_outBitC(result);
8085         // if(bit | ...)
8086         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8087             genIfxJump(ifx, "c");           
8088         goto release ;
8089     }
8090
8091     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
8092     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
8093     if((AOP_TYPE(right) == AOP_LIT) &&
8094        (AOP_TYPE(result) == AOP_CRY) &&
8095        (AOP_TYPE(left) != AOP_CRY)){
8096         if(lit){
8097           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8098             // result = 1
8099             if(size)
8100                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8101             else 
8102                 continueIfTrue(ifx);
8103             goto release;
8104         } else {
8105           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8106             // lit = 0, result = boolean(left)
8107             if(size)
8108                 pic16_emitcode(";XXX setb","c");
8109             pic16_toBoolean(right);
8110             if(size){
8111                 symbol *tlbl = newiTempLabel(NULL);
8112                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8113                 CLRC;
8114                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8115             } else {
8116                 genIfxJump (ifx,"a");
8117                 goto release;
8118             }
8119         }
8120         pic16_outBitC(result);
8121         goto release ;
8122     }
8123
8124     /* if left is same as result */
8125     if(pic16_sameRegs(AOP(result),AOP(left))){
8126       int know_W = -1;
8127       for(;size--; offset++,lit>>=8) {
8128         if(AOP_TYPE(right) == AOP_LIT){
8129           if((lit & 0xff) == 0)
8130             /*  or'ing with 0 has no effect */
8131             continue;
8132           else {
8133             int p = pic16_my_powof2(lit & 0xff);
8134             if(p>=0) {
8135               /* only one bit is set in the literal, so use a bsf instruction */
8136               pic16_emitpcode(POC_BSF,
8137                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8138             } else {
8139               if(know_W != (lit & 0xff))
8140                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8141               know_W = lit & 0xff;
8142               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8143             }
8144                     
8145           }
8146         } else {
8147           if (AOP_TYPE(left) == AOP_ACC) {
8148             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
8149             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8150           } else {                  
8151             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8152             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
8153
8154             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8155             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8156
8157           }
8158         }
8159       }
8160     } else {
8161         // left & result in different registers
8162         if(AOP_TYPE(result) == AOP_CRY){
8163             // result = bit
8164             // if(size), result in bit
8165             // if(!size && ifx), conditional oper: if(left | right)
8166             symbol *tlbl = newiTempLabel(NULL);
8167             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8168             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8169
8170
8171             if(size)
8172                 pic16_emitcode(";XXX setb","c");
8173             while(sizer--){
8174                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8175                 pic16_emitcode(";XXX orl","a,%s",
8176                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8177                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8178                 offset++;
8179             }
8180             if(size){
8181                 CLRC;
8182                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8183                 pic16_outBitC(result);
8184             } else if(ifx)
8185                 jmpTrueOrFalse(ifx, tlbl);
8186         } else for(;(size--);offset++){
8187           // normal case
8188           // result = left & right
8189           if(AOP_TYPE(right) == AOP_LIT){
8190             int t = (lit >> (offset*8)) & 0x0FFL;
8191             switch(t) { 
8192             case 0x00:
8193               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8194               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8195
8196               pic16_emitcode("movf","%s,w",
8197                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8198               pic16_emitcode("movwf","%s",
8199                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8200               break;
8201             default:
8202               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
8203               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8204               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8205
8206               pic16_emitcode("movlw","0x%x",t);
8207               pic16_emitcode("iorwf","%s,w",
8208                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8209               pic16_emitcode("movwf","%s",
8210                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8211               
8212             }
8213             continue;
8214           }
8215
8216           // faster than result <- left, anl result,right
8217           // and better if result is SFR
8218           if (AOP_TYPE(left) == AOP_ACC) {
8219             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
8220             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8221           } else {
8222             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8223             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8224
8225             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8226             pic16_emitcode("iorwf","%s,w",
8227                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8228           }
8229           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8230           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8231         }
8232     }
8233
8234 release :
8235     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8236     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8237     pic16_freeAsmop(result,NULL,ic,TRUE);     
8238 }
8239
8240 /*-----------------------------------------------------------------*/
8241 /* genXor - code for xclusive or                                   */
8242 /*-----------------------------------------------------------------*/
8243 static void genXor (iCode *ic, iCode *ifx)
8244 {
8245   operand *left, *right, *result;
8246   int size, offset=0;
8247   unsigned long lit = 0L;
8248
8249   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8250
8251   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8252   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8253   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8254
8255   /* if left is a literal & right is not ||
8256      if left needs acc & right does not */
8257   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8258       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8259     operand *tmp = right ;
8260     right = left;
8261     left = tmp;
8262   }
8263
8264   /* if result = right then exchange them */
8265   if(pic16_sameRegs(AOP(result),AOP(right))){
8266     operand *tmp = right ;
8267     right = left;
8268     left = tmp;
8269   }
8270
8271   /* if right is bit then exchange them */
8272   if (AOP_TYPE(right) == AOP_CRY &&
8273       AOP_TYPE(left) != AOP_CRY){
8274     operand *tmp = right ;
8275     right = left;
8276     left = tmp;
8277   }
8278   if(AOP_TYPE(right) == AOP_LIT)
8279     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8280
8281   size = AOP_SIZE(result);
8282
8283   // if(bit ^ yy)
8284   // xx = bit ^ yy;
8285   if (AOP_TYPE(left) == AOP_CRY){
8286     if(AOP_TYPE(right) == AOP_LIT){
8287       // c = bit & literal;
8288       if(lit>>1){
8289         // lit>>1  != 0 => result = 1
8290         if(AOP_TYPE(result) == AOP_CRY){
8291           if(size)
8292             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8293             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8294           else if(ifx)
8295             continueIfTrue(ifx);
8296           goto release;
8297         }
8298         pic16_emitcode("setb","c");
8299       } else{
8300         // lit == (0 or 1)
8301         if(lit == 0){
8302           // lit == 0, result = left
8303           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8304             goto release;
8305           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8306         } else{
8307           // lit == 1, result = not(left)
8308           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8309             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8310             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8311             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8312             goto release;
8313           } else {
8314             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8315             pic16_emitcode("cpl","c");
8316           }
8317         }
8318       }
8319
8320     } else {
8321       // right != literal
8322       symbol *tlbl = newiTempLabel(NULL);
8323       if (AOP_TYPE(right) == AOP_CRY){
8324         // c = bit ^ bit;
8325         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8326       }
8327       else{
8328         int sizer = AOP_SIZE(right);
8329         // c = bit ^ val
8330         // if val>>1 != 0, result = 1
8331         pic16_emitcode("setb","c");
8332         while(sizer){
8333           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8334           if(sizer == 1)
8335             // test the msb of the lsb
8336             pic16_emitcode("anl","a,#0xfe");
8337           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8338           sizer--;
8339         }
8340         // val = (0,1)
8341         pic16_emitcode("rrc","a");
8342       }
8343       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8344       pic16_emitcode("cpl","c");
8345       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8346     }
8347     // bit = c
8348     // val = c
8349     if(size)
8350       pic16_outBitC(result);
8351     // if(bit | ...)
8352     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8353       genIfxJump(ifx, "c");           
8354     goto release ;
8355   }
8356
8357   if(pic16_sameRegs(AOP(result),AOP(left))){
8358     /* if left is same as result */
8359     for(;size--; offset++) {
8360       if(AOP_TYPE(right) == AOP_LIT){
8361         int t  = (lit >> (offset*8)) & 0x0FFL;
8362         if(t == 0x00L)
8363           continue;
8364         else
8365           if (IS_AOP_PREG(left)) {
8366             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8367             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8368             pic16_aopPut(AOP(result),"a",offset);
8369           } else {
8370             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8371             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8372             pic16_emitcode("xrl","%s,%s",
8373                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8374                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8375           }
8376       } else {
8377         if (AOP_TYPE(left) == AOP_ACC)
8378           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8379         else {
8380           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8381           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8382 /*
8383           if (IS_AOP_PREG(left)) {
8384             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8385             pic16_aopPut(AOP(result),"a",offset);
8386           } else
8387             pic16_emitcode("xrl","%s,a",
8388                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8389 */
8390         }
8391       }
8392     }
8393   } else {
8394     // left & result in different registers
8395     if(AOP_TYPE(result) == AOP_CRY){
8396       // result = bit
8397       // if(size), result in bit
8398       // if(!size && ifx), conditional oper: if(left ^ right)
8399       symbol *tlbl = newiTempLabel(NULL);
8400       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8401       if(size)
8402         pic16_emitcode("setb","c");
8403       while(sizer--){
8404         if((AOP_TYPE(right) == AOP_LIT) &&
8405            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8406           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8407         } else {
8408           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8409           pic16_emitcode("xrl","a,%s",
8410                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8411         }
8412         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8413         offset++;
8414       }
8415       if(size){
8416         CLRC;
8417         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8418         pic16_outBitC(result);
8419       } else if(ifx)
8420         jmpTrueOrFalse(ifx, tlbl);
8421     } else for(;(size--);offset++){
8422       // normal case
8423       // result = left & right
8424       if(AOP_TYPE(right) == AOP_LIT){
8425         int t = (lit >> (offset*8)) & 0x0FFL;
8426         switch(t) { 
8427         case 0x00:
8428           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8429           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8430           pic16_emitcode("movf","%s,w",
8431                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8432           pic16_emitcode("movwf","%s",
8433                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8434           break;
8435         case 0xff:
8436           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8437           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8438           pic16_emitcode("comf","%s,w",
8439                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8440           pic16_emitcode("movwf","%s",
8441                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8442           break;
8443         default:
8444           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8445           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8446           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8447           pic16_emitcode("movlw","0x%x",t);
8448           pic16_emitcode("xorwf","%s,w",
8449                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8450           pic16_emitcode("movwf","%s",
8451                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8452
8453         }
8454         continue;
8455       }
8456
8457       // faster than result <- left, anl result,right
8458       // and better if result is SFR
8459       if (AOP_TYPE(left) == AOP_ACC) {
8460         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8461         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8462       } else {
8463         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8464         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8465         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8466         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8467       }
8468       if ( AOP_TYPE(result) != AOP_ACC){
8469         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8470         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8471       }
8472     }
8473   }
8474
8475   release :
8476     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8477   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8478   pic16_freeAsmop(result,NULL,ic,TRUE);     
8479 }
8480
8481 /*-----------------------------------------------------------------*/
8482 /* genInline - write the inline code out                           */
8483 /*-----------------------------------------------------------------*/
8484 static void genInline (iCode *ic)
8485 {
8486   char *buffer, *bp, *bp1;
8487     
8488         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8489
8490         _G.inLine += (!options.asmpeep);
8491
8492         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8493         strcpy(buffer,IC_INLINE(ic));
8494
8495 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
8496
8497         /* emit each line as a code */
8498         while (*bp) {
8499                 if (*bp == '\n') {
8500                         *bp++ = '\0';
8501
8502                         if(*bp1)
8503                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8504                         bp1 = bp;
8505                 } else {
8506                         if (*bp == ':') {
8507                                 bp++;
8508                                 *bp = '\0';
8509                                 bp++;
8510
8511                                 /* print label, use this special format with NULL directive
8512                                  * to denote that the argument should not be indented with tab */
8513                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8514                                 bp1 = bp;
8515                         } else
8516                                 bp++;
8517                 }
8518         }
8519
8520         if ((bp1 != bp) && *bp1)
8521                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8522
8523
8524     Safe_free(buffer);
8525
8526     _G.inLine -= (!options.asmpeep);
8527 }
8528
8529 /*-----------------------------------------------------------------*/
8530 /* genRRC - rotate right with carry                                */
8531 /*-----------------------------------------------------------------*/
8532 static void genRRC (iCode *ic)
8533 {
8534   operand *left , *result ;
8535   int size, offset = 0, same;
8536
8537   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8538
8539   /* rotate right with carry */
8540   left = IC_LEFT(ic);
8541   result=IC_RESULT(ic);
8542   pic16_aopOp (left,ic,FALSE);
8543   pic16_aopOp (result,ic,FALSE);
8544
8545   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8546
8547   same = pic16_sameRegs(AOP(result),AOP(left));
8548
8549   size = AOP_SIZE(result);    
8550
8551   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8552
8553   /* get the lsb and put it into the carry */
8554   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8555
8556   offset = 0 ;
8557
8558   while(size--) {
8559
8560     if(same) {
8561       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8562     } else {
8563       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8564       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8565     }
8566
8567     offset++;
8568   }
8569
8570   pic16_freeAsmop(left,NULL,ic,TRUE);
8571   pic16_freeAsmop(result,NULL,ic,TRUE);
8572 }
8573
8574 /*-----------------------------------------------------------------*/
8575 /* genRLC - generate code for rotate left with carry               */
8576 /*-----------------------------------------------------------------*/
8577 static void genRLC (iCode *ic)
8578 {    
8579   operand *left , *result ;
8580   int size, offset = 0;
8581   int same;
8582
8583   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8584   /* rotate right with carry */
8585   left = IC_LEFT(ic);
8586   result=IC_RESULT(ic);
8587   pic16_aopOp (left,ic,FALSE);
8588   pic16_aopOp (result,ic,FALSE);
8589
8590   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8591
8592   same = pic16_sameRegs(AOP(result),AOP(left));
8593
8594   /* move it to the result */
8595   size = AOP_SIZE(result);    
8596
8597   /* get the msb and put it into the carry */
8598   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8599
8600   offset = 0 ;
8601
8602   while(size--) {
8603
8604     if(same) {
8605       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8606     } else {
8607       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8608       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8609     }
8610
8611     offset++;
8612   }
8613
8614
8615   pic16_freeAsmop(left,NULL,ic,TRUE);
8616   pic16_freeAsmop(result,NULL,ic,TRUE);
8617 }
8618
8619
8620 /* gpasm can get the highest order bit with HIGH/UPPER
8621  * so the following probably is not needed -- VR */
8622  
8623 /*-----------------------------------------------------------------*/
8624 /* genGetHbit - generates code get highest order bit               */
8625 /*-----------------------------------------------------------------*/
8626 static void genGetHbit (iCode *ic)
8627 {
8628     operand *left, *result;
8629     left = IC_LEFT(ic);
8630     result=IC_RESULT(ic);
8631     pic16_aopOp (left,ic,FALSE);
8632     pic16_aopOp (result,ic,FALSE);
8633
8634     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8635     /* get the highest order byte into a */
8636     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8637     if(AOP_TYPE(result) == AOP_CRY){
8638         pic16_emitcode("rlc","a");
8639         pic16_outBitC(result);
8640     }
8641     else{
8642         pic16_emitcode("rl","a");
8643         pic16_emitcode("anl","a,#0x01");
8644         pic16_outAcc(result);
8645     }
8646
8647
8648     pic16_freeAsmop(left,NULL,ic,TRUE);
8649     pic16_freeAsmop(result,NULL,ic,TRUE);
8650 }
8651
8652 #if 0
8653 /*-----------------------------------------------------------------*/
8654 /* AccRol - rotate left accumulator by known count                 */
8655 /*-----------------------------------------------------------------*/
8656 static void AccRol (int shCount)
8657 {
8658     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8659     shCount &= 0x0007;              // shCount : 0..7
8660     switch(shCount){
8661         case 0 :
8662             break;
8663         case 1 :
8664             pic16_emitcode("rl","a");
8665             break;
8666         case 2 :
8667             pic16_emitcode("rl","a");
8668             pic16_emitcode("rl","a");
8669             break;
8670         case 3 :
8671             pic16_emitcode("swap","a");
8672             pic16_emitcode("rr","a");
8673             break;
8674         case 4 :
8675             pic16_emitcode("swap","a");
8676             break;
8677         case 5 :
8678             pic16_emitcode("swap","a");
8679             pic16_emitcode("rl","a");
8680             break;
8681         case 6 :
8682             pic16_emitcode("rr","a");
8683             pic16_emitcode("rr","a");
8684             break;
8685         case 7 :
8686             pic16_emitcode("rr","a");
8687             break;
8688     }
8689 }
8690 #endif
8691
8692 /*-----------------------------------------------------------------*/
8693 /* AccLsh - left shift accumulator by known count                  */
8694 /*-----------------------------------------------------------------*/
8695 static void AccLsh (int shCount)
8696 {
8697         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8698         switch(shCount){
8699                 case 0 :
8700                         return;
8701                         break;
8702                 case 1 :
8703                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8704                         break;
8705                 case 2 :
8706                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8707                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8708                         break;
8709                 case 3 :
8710                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8711                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8712                         break;
8713                 case 4 :
8714                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8715                         break;
8716                 case 5 :
8717                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8718                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8719                         break;
8720                 case 6 :
8721                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8722                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8723                         break;
8724                 case 7 :
8725                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8726                         break;
8727         }
8728
8729         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8730 }
8731
8732 /*-----------------------------------------------------------------*/
8733 /* AccRsh - right shift accumulator by known count                 */
8734 /*-----------------------------------------------------------------*/
8735 static void AccRsh (int shCount, int andmask)
8736 {
8737         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8738         switch(shCount){
8739                 case 0 :
8740                         return; break;
8741                 case 1 :
8742                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8743                         break;
8744                 case 2 :
8745                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8746                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8747                         break;
8748                 case 3 :
8749                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8750                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8751                         break;
8752                 case 4 :
8753                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8754                         break;
8755                 case 5 :
8756                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8757                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8758                         break;
8759                 case 6 :
8760                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8761                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8762                         break;
8763                 case 7 :
8764                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8765                         break;
8766         }
8767         
8768         if(andmask)
8769                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8770         else
8771                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8772 }
8773
8774 #if 0
8775 /*-----------------------------------------------------------------*/
8776 /* AccSRsh - signed right shift accumulator by known count                 */
8777 /*-----------------------------------------------------------------*/
8778 static void AccSRsh (int shCount)
8779 {
8780     symbol *tlbl ;
8781     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8782     if(shCount != 0){
8783         if(shCount == 1){
8784             pic16_emitcode("mov","c,acc.7");
8785             pic16_emitcode("rrc","a");
8786         } else if(shCount == 2){
8787             pic16_emitcode("mov","c,acc.7");
8788             pic16_emitcode("rrc","a");
8789             pic16_emitcode("mov","c,acc.7");
8790             pic16_emitcode("rrc","a");
8791         } else {
8792             tlbl = newiTempLabel(NULL);
8793             /* rotate right accumulator */
8794             AccRol(8 - shCount);
8795             /* and kill the higher order bits */
8796             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8797             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8798             pic16_emitcode("orl","a,#0x%02x",
8799                      (unsigned char)~SRMask[shCount]);
8800             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8801         }
8802     }
8803 }
8804 #endif
8805
8806 /*-----------------------------------------------------------------*/
8807 /* shiftR1Left2Result - shift right one byte from left to result   */
8808 /*-----------------------------------------------------------------*/
8809 static void shiftR1Left2ResultSigned (operand *left, int offl,
8810                                 operand *result, int offr,
8811                                 int shCount)
8812 {
8813   int same;
8814
8815   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8816
8817   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8818
8819   switch(shCount) {
8820   case 1:
8821     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8822     if(same) 
8823       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8824     else {
8825       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8826       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8827     }
8828
8829     break;
8830   case 2:
8831
8832     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8833     if(same) 
8834       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8835     else {
8836       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8837       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8838     }
8839     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8840     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8841
8842     break;
8843
8844   case 3:
8845     if(same)
8846       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8847     else {
8848       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8849       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8850     }
8851
8852     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8853     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8854     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8855
8856     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8857     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8858
8859     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8860     break;
8861
8862   case 4:
8863     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8864     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8865     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8866     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8867     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8868     break;
8869   case 5:
8870     if(same) {
8871       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8872     } else {
8873       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8874       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8875     }
8876     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8877     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8878     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8879     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8880     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8881     break;
8882
8883   case 6:
8884     if(same) {
8885       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8886       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8887       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8888       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8889       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8890       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8891     } else {
8892       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8893       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8894       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8895       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8896       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8897     }
8898     break;
8899
8900   case 7:
8901     if(same) {
8902       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8903       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8904       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8905       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8906     } else {
8907       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8908       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8909       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8910     }
8911
8912   default:
8913     break;
8914   }
8915 }
8916
8917 /*-----------------------------------------------------------------*/
8918 /* shiftR1Left2Result - shift right one byte from left to result   */
8919 /*-----------------------------------------------------------------*/
8920 static void shiftR1Left2Result (operand *left, int offl,
8921                                 operand *result, int offr,
8922                                 int shCount, int sign)
8923 {
8924   int same;
8925
8926   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8927
8928   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8929
8930   /* Copy the msb into the carry if signed. */
8931   if(sign) {
8932     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8933     return;
8934   }
8935
8936
8937
8938   switch(shCount) {
8939   case 1:
8940     emitCLRC;
8941     if(same) 
8942       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8943     else {
8944       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8945       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8946     }
8947     break;
8948   case 2:
8949     emitCLRC;
8950     if(same) {
8951       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8952     } else {
8953       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8954       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8955     }
8956     emitCLRC;
8957     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8958
8959     break;
8960   case 3:
8961     if(same)
8962       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8963     else {
8964       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8965       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8966     }
8967
8968     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8969     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8970     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8971     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8972     break;
8973       
8974   case 4:
8975     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8976     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8977     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8978     break;
8979
8980   case 5:
8981     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8982     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8983     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8984     //emitCLRC;
8985     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8986
8987     break;
8988   case 6:
8989
8990     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8991     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8992     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8993     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8994     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8995     break;
8996
8997   case 7:
8998
8999     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9000     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9001     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9002
9003     break;
9004
9005   default:
9006     break;
9007   }
9008 }
9009
9010 /*-----------------------------------------------------------------*/
9011 /* shiftL1Left2Result - shift left one byte from left to result    */
9012 /*-----------------------------------------------------------------*/
9013 static void shiftL1Left2Result (operand *left, int offl,
9014                                 operand *result, int offr, int shCount)
9015 {
9016   int same;
9017
9018   //    char *l;
9019   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9020
9021   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9022   DEBUGpic16_emitcode ("; ***","same =  %d",same);
9023     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9024     //    MOVA(l);
9025     /* shift left accumulator */
9026     //AccLsh(shCount); // don't comment out just yet...
9027   //    pic16_aopPut(AOP(result),"a",offr);
9028
9029   switch(shCount) {
9030   case 1:
9031     /* Shift left 1 bit position */
9032     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9033     if(same) {
9034       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9035     } else {
9036       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9037       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9038     }
9039     break;
9040   case 2:
9041     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9042     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9043     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9044     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9045     break;
9046   case 3:
9047     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9048     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9049     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9050     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9051     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9052     break;
9053   case 4:
9054     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9055     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9056     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9057     break;
9058   case 5:
9059     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9060     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9061     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9062     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9063     break;
9064   case 6:
9065     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9066     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9067     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9068     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9069     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9070     break;
9071   case 7:
9072     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9073     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9074     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9075     break;
9076
9077   default:
9078     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9079   }
9080
9081 }
9082
9083 /*-----------------------------------------------------------------*/
9084 /* movLeft2Result - move byte from left to result                  */
9085 /*-----------------------------------------------------------------*/
9086 static void movLeft2Result (operand *left, int offl,
9087                             operand *result, int offr)
9088 {
9089   char *l;
9090   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9091   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9092     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9093
9094     if (*l == '@' && (IS_AOP_PREG(result))) {
9095       pic16_emitcode("mov","a,%s",l);
9096       pic16_aopPut(AOP(result),"a",offr);
9097     } else {
9098       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9099       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9100     }
9101   }
9102 }
9103
9104 /*-----------------------------------------------------------------*/
9105 /* shiftL2Left2Result - shift left two bytes from left to result   */
9106 /*-----------------------------------------------------------------*/
9107 static void shiftL2Left2Result (operand *left, int offl,
9108                                 operand *result, int offr, int shCount)
9109 {
9110   int same = pic16_sameRegs(AOP(result), AOP(left));
9111   int i;
9112
9113   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9114
9115   if (same && (offl != offr)) { // shift bytes
9116     if (offr > offl) {
9117        for(i=1;i>-1;i--) {
9118          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9119          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9120        }
9121     } else { // just treat as different later on
9122                 same = 0;
9123     }
9124   }
9125
9126   if(same) {
9127     switch(shCount) {
9128     case 0:
9129       break;
9130     case 1:
9131     case 2:
9132     case 3:
9133
9134       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9135       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9136       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9137
9138       while(--shCount) {
9139                 emitCLRC;
9140                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9141                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9142       }
9143
9144       break;
9145     case 4:
9146     case 5:
9147       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9148       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9149       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9150       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9151       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9152       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9153       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9154       if(shCount >=5) {
9155                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9156                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9157       }
9158       break;
9159     case 6:
9160       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9161       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9162       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9163       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9164       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9165       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9166       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9167       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9168       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9169       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9170       break;
9171     case 7:
9172       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9173       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9174       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9175       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9176       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9177     }
9178
9179   } else {
9180     switch(shCount) {
9181     case 0:
9182       break;
9183     case 1:
9184     case 2:
9185     case 3:
9186       /* note, use a mov/add for the shift since the mov has a
9187          chance of getting optimized out */
9188       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9189       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9190       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9191       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9192       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9193
9194       while(--shCount) {
9195                 emitCLRC;
9196                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9197                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9198       }
9199       break;
9200
9201     case 4:
9202     case 5:
9203       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9204       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9205       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9206       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9207       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9208       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9209       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9210       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9211
9212
9213       if(shCount == 5) {
9214                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9215                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9216       }
9217       break;
9218     case 6:
9219       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9220       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9221       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9222       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9223
9224       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9225       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9226       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9227       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9228       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9229       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9230       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9231       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9232       break;
9233     case 7:
9234       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9235       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9236       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9237       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9238       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9239     }
9240   }
9241
9242 }
9243 /*-----------------------------------------------------------------*/
9244 /* shiftR2Left2Result - shift right two bytes from left to result  */
9245 /*-----------------------------------------------------------------*/
9246 static void shiftR2Left2Result (operand *left, int offl,
9247                                 operand *result, int offr,
9248                                 int shCount, int sign)
9249 {
9250   int same = pic16_sameRegs(AOP(result), AOP(left));
9251   int i;
9252   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9253
9254   if (same && (offl != offr)) { // shift right bytes
9255     if (offr < offl) {
9256        for(i=0;i<2;i++) {
9257          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9258          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9259        }
9260     } else { // just treat as different later on
9261                 same = 0;
9262     }
9263   }
9264
9265   switch(shCount) {
9266   case 0:
9267     break;
9268   case 1:
9269   case 2:
9270   case 3:
9271     if(sign)
9272       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9273     else
9274       emitCLRC;
9275
9276     if(same) {
9277       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9278       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9279     } else {
9280       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9281       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9282       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9283       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9284     }
9285
9286     while(--shCount) {
9287       if(sign)
9288                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9289       else
9290                 emitCLRC;
9291       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9292       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9293     }
9294     break;
9295   case 4:
9296   case 5:
9297     if(same) {
9298
9299       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9300       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9301       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9302
9303       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9304       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9305       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9306       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9307     } else {
9308       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9309       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9310       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9311
9312       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9313       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9314       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9315       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9316       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9317     }
9318
9319     if(shCount >=5) {
9320       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9321       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9322     }
9323
9324     if(sign) {
9325       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9326       pic16_emitpcode(POC_BTFSC, 
9327                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9328       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9329     }
9330
9331     break;
9332
9333   case 6:
9334     if(same) {
9335
9336       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9337       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9338
9339       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9340       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9341       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9342       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9343       if(sign) {
9344         pic16_emitpcode(POC_BTFSC, 
9345                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9346         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9347       }
9348       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9349       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9350       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9351       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9352     } else {
9353       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9354       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9355       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9356       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9357       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9358       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9359       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9360       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9361       if(sign) {
9362         pic16_emitpcode(POC_BTFSC, 
9363                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9364         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9365       }
9366       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9367       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9368
9369         
9370     }
9371
9372     break;
9373   case 7:
9374     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9375     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9376     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9377     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9378     if(sign) {
9379       emitSKPNC;
9380       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9381     } else 
9382       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9383   }
9384 }
9385
9386
9387 /*-----------------------------------------------------------------*/
9388 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9389 /*-----------------------------------------------------------------*/
9390 static void shiftLLeftOrResult (operand *left, int offl,
9391                                 operand *result, int offr, int shCount)
9392 {
9393     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9394
9395     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9396     /* shift left accumulator */
9397     AccLsh(shCount);
9398     /* or with result */
9399     /* back to result */
9400     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9401 }
9402
9403 /*-----------------------------------------------------------------*/
9404 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9405 /*-----------------------------------------------------------------*/
9406 static void shiftRLeftOrResult (operand *left, int offl,
9407                                 operand *result, int offr, int shCount)
9408 {
9409     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9410     
9411     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9412     /* shift right accumulator */
9413     AccRsh(shCount, 1);
9414     /* or with result */
9415     /* back to result */
9416     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9417 }
9418
9419 /*-----------------------------------------------------------------*/
9420 /* genlshOne - left shift a one byte quantity by known count       */
9421 /*-----------------------------------------------------------------*/
9422 static void genlshOne (operand *result, operand *left, int shCount)
9423 {       
9424     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9425     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9426 }
9427
9428 /*-----------------------------------------------------------------*/
9429 /* genlshTwo - left shift two bytes by known amount != 0           */
9430 /*-----------------------------------------------------------------*/
9431 static void genlshTwo (operand *result,operand *left, int shCount)
9432 {
9433     int size;
9434     
9435     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9436     size = pic16_getDataSize(result);
9437
9438     /* if shCount >= 8 */
9439     if (shCount >= 8) {
9440         shCount -= 8 ;
9441
9442         if (size > 1){
9443             if (shCount)
9444                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9445             else 
9446                 movLeft2Result(left, LSB, result, MSB16);
9447         }
9448         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9449     }
9450
9451     /*  1 <= shCount <= 7 */
9452     else {  
9453         if(size == 1)
9454             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9455         else 
9456             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9457     }
9458 }
9459
9460 /*-----------------------------------------------------------------*/
9461 /* shiftLLong - shift left one long from left to result            */
9462 /* offr = LSB or MSB16                                             */
9463 /*-----------------------------------------------------------------*/
9464 static void shiftLLong (operand *left, operand *result, int offr )
9465 {
9466     int size = AOP_SIZE(result);
9467     int same = pic16_sameRegs(AOP(left),AOP(result));
9468         int i;
9469
9470     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9471
9472         if (same && (offr == MSB16)) { //shift one byte
9473                 for(i=size-1;i>=MSB16;i--) {
9474                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9475                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9476                 }
9477         } else {
9478                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9479         }
9480         
9481     if (size > LSB+offr ){
9482                 if (same) {
9483                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9484                 } else {
9485                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9486                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9487                 }
9488          }
9489
9490     if(size > MSB16+offr){
9491                 if (same) {
9492                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9493                 } else {
9494                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9495                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9496                 }
9497     }
9498
9499     if(size > MSB24+offr){
9500                 if (same) {
9501                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9502                 } else {
9503                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9504                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9505                 }
9506     }
9507
9508     if(size > MSB32+offr){
9509                 if (same) {
9510                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9511                 } else {
9512                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9513                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9514                 }
9515     }
9516     if(offr != LSB)
9517                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9518
9519 }
9520
9521 /*-----------------------------------------------------------------*/
9522 /* genlshFour - shift four byte by a known amount != 0             */
9523 /*-----------------------------------------------------------------*/
9524 static void genlshFour (operand *result, operand *left, int shCount)
9525 {
9526     int size;
9527
9528     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9529     size = AOP_SIZE(result);
9530
9531     /* if shifting more that 3 bytes */
9532     if (shCount >= 24 ) {
9533         shCount -= 24;
9534         if (shCount)
9535             /* lowest order of left goes to the highest
9536             order of the destination */
9537             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9538         else
9539             movLeft2Result(left, LSB, result, MSB32);
9540
9541                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9542                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9543                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9544
9545         return;
9546     }
9547
9548     /* more than two bytes */
9549     else if ( shCount >= 16 ) {
9550         /* lower order two bytes goes to higher order two bytes */
9551         shCount -= 16;
9552         /* if some more remaining */
9553         if (shCount)
9554             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9555         else {
9556             movLeft2Result(left, MSB16, result, MSB32);
9557             movLeft2Result(left, LSB, result, MSB24);
9558         }
9559                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9560                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9561         return;
9562     }    
9563
9564     /* if more than 1 byte */
9565     else if ( shCount >= 8 ) {
9566         /* lower order three bytes goes to higher order  three bytes */
9567         shCount -= 8;
9568         if(size == 2){
9569             if(shCount)
9570                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9571             else
9572                 movLeft2Result(left, LSB, result, MSB16);
9573         }
9574         else{   /* size = 4 */
9575             if(shCount == 0){
9576                 movLeft2Result(left, MSB24, result, MSB32);
9577                 movLeft2Result(left, MSB16, result, MSB24);
9578                 movLeft2Result(left, LSB, result, MSB16);
9579                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9580             }
9581             else if(shCount == 1)
9582                 shiftLLong(left, result, MSB16);
9583             else{
9584                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9585                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9586                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9587                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9588             }
9589         }
9590     }
9591
9592     /* 1 <= shCount <= 7 */
9593     else if(shCount <= 3)
9594     { 
9595         shiftLLong(left, result, LSB);
9596         while(--shCount >= 1)
9597             shiftLLong(result, result, LSB);
9598     }
9599     /* 3 <= shCount <= 7, optimize */
9600     else{
9601         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9602         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9603         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9604     }
9605 }
9606
9607 /*-----------------------------------------------------------------*/
9608 /* genLeftShiftLiteral - left shifting by known count              */
9609 /*-----------------------------------------------------------------*/
9610 void pic16_genLeftShiftLiteral (operand *left,
9611                                  operand *right,
9612                                  operand *result,
9613                                  iCode *ic)
9614 {    
9615     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9616     int size;
9617
9618     FENTRY;
9619     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9620     pic16_freeAsmop(right,NULL,ic,TRUE);
9621
9622     pic16_aopOp(left,ic,FALSE);
9623     pic16_aopOp(result,ic,FALSE);
9624
9625     size = getSize(operandType(result));
9626
9627 #if VIEW_SIZE
9628     pic16_emitcode("; shift left ","result %d, left %d",size,
9629              AOP_SIZE(left));
9630 #endif
9631
9632     /* I suppose that the left size >= result size */
9633     if(shCount == 0){
9634         while(size--){
9635             movLeft2Result(left, size, result, size);
9636         }
9637     }
9638
9639     else if(shCount >= (size * 8))
9640         while(size--)
9641             pic16_aopPut(AOP(result),zero,size);
9642     else{
9643         switch (size) {
9644             case 1:
9645                 genlshOne (result,left,shCount);
9646                 break;
9647
9648             case 2:
9649             case 3:
9650                 genlshTwo (result,left,shCount);
9651                 break;
9652
9653             case 4:
9654                 genlshFour (result,left,shCount);
9655                 break;
9656         }
9657     }
9658     pic16_freeAsmop(left,NULL,ic,TRUE);
9659     pic16_freeAsmop(result,NULL,ic,TRUE);
9660 }
9661
9662 /*-----------------------------------------------------------------*
9663  * genMultiAsm - repeat assembly instruction for size of register.
9664  * if endian == 1, then the high byte (i.e base address + size of 
9665  * register) is used first else the low byte is used first;
9666  *-----------------------------------------------------------------*/
9667 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9668 {
9669
9670   int offset = 0;
9671
9672   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9673
9674   if(!reg)
9675     return;
9676
9677   if(!endian) {
9678     endian = 1;
9679   } else {
9680     endian = -1;
9681     offset = size-1;
9682   }
9683
9684   while(size--) {
9685     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9686     offset += endian;
9687   }
9688
9689 }
9690
9691 #if !(USE_GENERIC_SIGNED_SHIFT)
9692 /*-----------------------------------------------------------------*/
9693 /* genLeftShift - generates code for left shifting                 */
9694 /*-----------------------------------------------------------------*/
9695 static void genLeftShift (iCode *ic)
9696 {
9697   operand *left,*right, *result;
9698   int size, offset;
9699 //  char *l;
9700   symbol *tlbl , *tlbl1;
9701   pCodeOp *pctemp;
9702
9703   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9704
9705   right = IC_RIGHT(ic);
9706   left  = IC_LEFT(ic);
9707   result = IC_RESULT(ic);
9708
9709   pic16_aopOp(right,ic,FALSE);
9710
9711   /* if the shift count is known then do it 
9712      as efficiently as possible */
9713   if (AOP_TYPE(right) == AOP_LIT) {
9714     pic16_genLeftShiftLiteral (left,right,result,ic);
9715     return ;
9716   }
9717
9718   /* shift count is unknown then we have to form
9719    * a loop. Get the loop count in WREG : Note: we take
9720    * only the lower order byte since shifting
9721    * more than 32 bits make no sense anyway, ( the
9722    * largest size of an object can be only 32 bits ) */
9723   
9724   pic16_aopOp(left,ic,FALSE);
9725   pic16_aopOp(result,ic,FALSE);
9726
9727   /* now move the left to the result if they are not the
9728    * same, and if size > 1,
9729    * and if right is not same to result (!!!) -- VR */
9730   if (!pic16_sameRegs(AOP(left),AOP(result))
9731       && (AOP_SIZE(result) > 1)) {
9732
9733     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9734
9735     size = AOP_SIZE(result);
9736     offset=0;
9737     while (size--) {
9738
9739 #if 0
9740       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9741       if (*l == '@' && (IS_AOP_PREG(result))) {
9742
9743           pic16_emitcode("mov","a,%s",l);
9744           pic16_aopPut(AOP(result),"a",offset);
9745       } else
9746 #endif
9747       {
9748         /* we don't know if left is a literal or a register, take care -- VR */
9749         mov2f(AOP(result), AOP(left), offset);
9750       }
9751       offset++;
9752     }
9753   }
9754
9755   size = AOP_SIZE(result);
9756
9757   /* if it is only one byte then */
9758   if (size == 1) {
9759     if(optimized_for_speed) {
9760       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9761       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9762       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9763       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9764       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9765       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9766       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9767       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9768       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9769       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9770       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9771       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9772     } else {
9773
9774       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9775
9776       tlbl = newiTempLabel(NULL);
9777
9778 #if 1
9779       /* this is already done, why change it? */
9780       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9781                 mov2f(AOP(result), AOP(left), 0);
9782       }
9783 #endif
9784
9785       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9786       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9787       pic16_emitpLabel(tlbl->key);
9788       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9789       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9790       emitSKPC;
9791       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9792     }
9793     goto release ;
9794   }
9795     
9796   if (pic16_sameRegs(AOP(left),AOP(result))) {
9797
9798     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9799     
9800     tlbl = newiTempLabel(NULL);
9801     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9802     genMultiAsm(POC_RRCF, result, size,1);
9803     pic16_emitpLabel(tlbl->key);
9804     genMultiAsm(POC_RLCF, result, size,0);
9805     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9806     emitSKPC;
9807     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9808     goto release;
9809   }
9810
9811   //tlbl = newiTempLabel(NULL);
9812   //offset = 0 ;   
9813   //tlbl1 = newiTempLabel(NULL);
9814
9815   //reAdjustPreg(AOP(result));    
9816     
9817   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9818   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9819   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9820   //MOVA(l);
9821   //pic16_emitcode("add","a,acc");         
9822   //pic16_aopPut(AOP(result),"a",offset++);
9823   //while (--size) {
9824   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9825   //  MOVA(l);
9826   //  pic16_emitcode("rlc","a");         
9827   //  pic16_aopPut(AOP(result),"a",offset++);
9828   //}
9829   //reAdjustPreg(AOP(result));
9830
9831   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9832   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9833
9834
9835   tlbl = newiTempLabel(NULL);
9836   tlbl1= newiTempLabel(NULL);
9837
9838   size = AOP_SIZE(result);
9839   offset = 1;
9840
9841   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9842
9843   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9844
9845   /* offset should be 0, 1 or 3 */
9846   
9847   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9848   emitSKPNZ;
9849   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9850
9851   pic16_emitpcode(POC_MOVWF, pctemp);
9852
9853
9854   pic16_emitpLabel(tlbl->key);
9855
9856   emitCLRC;
9857   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9858   while(--size)
9859     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9860
9861   pic16_emitpcode(POC_DECFSZ,  pctemp);
9862   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9863   pic16_emitpLabel(tlbl1->key);
9864
9865   pic16_popReleaseTempReg(pctemp,1);
9866
9867
9868  release:
9869   pic16_freeAsmop (right,NULL,ic,TRUE);
9870   pic16_freeAsmop(left,NULL,ic,TRUE);
9871   pic16_freeAsmop(result,NULL,ic,TRUE);
9872 }
9873 #endif
9874
9875
9876 #if 0
9877 #error old code (left here for reference)
9878 /*-----------------------------------------------------------------*/
9879 /* genLeftShift - generates code for left shifting                 */
9880 /*-----------------------------------------------------------------*/
9881 static void genLeftShift (iCode *ic)
9882 {
9883   operand *left,*right, *result;
9884   int size, offset;
9885   char *l;
9886   symbol *tlbl , *tlbl1;
9887   pCodeOp *pctemp;
9888
9889   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9890
9891   right = IC_RIGHT(ic);
9892   left  = IC_LEFT(ic);
9893   result = IC_RESULT(ic);
9894
9895   pic16_aopOp(right,ic,FALSE);
9896
9897   /* if the shift count is known then do it 
9898      as efficiently as possible */
9899   if (AOP_TYPE(right) == AOP_LIT) {
9900     pic16_genLeftShiftLiteral (left,right,result,ic);
9901     return ;
9902   }
9903
9904   /* shift count is unknown then we have to form 
9905      a loop get the loop count in B : Note: we take
9906      only the lower order byte since shifting
9907      more that 32 bits make no sense anyway, ( the
9908      largest size of an object can be only 32 bits ) */  
9909
9910     
9911   pic16_aopOp(left,ic,FALSE);
9912   pic16_aopOp(result,ic,FALSE);
9913
9914   /* now move the left to the result if they are not the
9915      same */
9916   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9917       AOP_SIZE(result) > 1) {
9918
9919     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9920
9921     size = AOP_SIZE(result);
9922     offset=0;
9923     while (size--) {
9924       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9925       if (*l == '@' && (IS_AOP_PREG(result))) {
9926
9927         pic16_emitcode("mov","a,%s",l);
9928         pic16_aopPut(AOP(result),"a",offset);
9929       } else {
9930
9931         /* we don't know if left is a literal or a register, take care -- VR */
9932         mov2f(AOP(result), AOP(left), offset);
9933       }
9934       offset++;
9935     }
9936   }
9937
9938   size = AOP_SIZE(result);
9939
9940   /* if it is only one byte then */
9941   if (size == 1) {
9942     if(optimized_for_speed) {
9943       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9944       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9945       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9946       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9947       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9948       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9949       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9950       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9951       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9952       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9953       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9954       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9955     } else {
9956
9957       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9958
9959       tlbl = newiTempLabel(NULL);
9960       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9961                 mov2f(AOP(result), AOP(left), 0);
9962                 
9963 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9964 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9965       }
9966
9967       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9968       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9969       pic16_emitpLabel(tlbl->key);
9970       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9971       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9972       emitSKPC;
9973       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9974     }
9975     goto release ;
9976   }
9977     
9978   if (pic16_sameRegs(AOP(left),AOP(result))) {
9979
9980     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9981     
9982     tlbl = newiTempLabel(NULL);
9983     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9984     genMultiAsm(POC_RRCF, result, size,1);
9985     pic16_emitpLabel(tlbl->key);
9986     genMultiAsm(POC_RLCF, result, size,0);
9987     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9988     emitSKPC;
9989     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9990     goto release;
9991   }
9992
9993   //tlbl = newiTempLabel(NULL);
9994   //offset = 0 ;   
9995   //tlbl1 = newiTempLabel(NULL);
9996
9997   //reAdjustPreg(AOP(result));    
9998     
9999   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
10000   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10001   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10002   //MOVA(l);
10003   //pic16_emitcode("add","a,acc");         
10004   //pic16_aopPut(AOP(result),"a",offset++);
10005   //while (--size) {
10006   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10007   //  MOVA(l);
10008   //  pic16_emitcode("rlc","a");         
10009   //  pic16_aopPut(AOP(result),"a",offset++);
10010   //}
10011   //reAdjustPreg(AOP(result));
10012
10013   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10014   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10015
10016
10017   tlbl = newiTempLabel(NULL);
10018   tlbl1= newiTempLabel(NULL);
10019
10020   size = AOP_SIZE(result);
10021   offset = 1;
10022
10023   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10024
10025   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10026
10027   /* offset should be 0, 1 or 3 */
10028   
10029   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10030   emitSKPNZ;
10031   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10032
10033   pic16_emitpcode(POC_MOVWF, pctemp);
10034
10035
10036   pic16_emitpLabel(tlbl->key);
10037
10038   emitCLRC;
10039   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
10040   while(--size)
10041     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10042
10043   pic16_emitpcode(POC_DECFSZ,  pctemp);
10044   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10045   pic16_emitpLabel(tlbl1->key);
10046
10047   pic16_popReleaseTempReg(pctemp,1);
10048
10049
10050  release:
10051   pic16_freeAsmop (right,NULL,ic,TRUE);
10052   pic16_freeAsmop(left,NULL,ic,TRUE);
10053   pic16_freeAsmop(result,NULL,ic,TRUE);
10054 }
10055 #endif
10056
10057 /*-----------------------------------------------------------------*/
10058 /* genrshOne - right shift a one byte quantity by known count      */
10059 /*-----------------------------------------------------------------*/
10060 static void genrshOne (operand *result, operand *left,
10061                        int shCount, int sign)
10062 {
10063     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10064     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10065 }
10066
10067 /*-----------------------------------------------------------------*/
10068 /* genrshTwo - right shift two bytes by known amount != 0          */
10069 /*-----------------------------------------------------------------*/
10070 static void genrshTwo (operand *result,operand *left,
10071                        int shCount, int sign)
10072 {
10073   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10074   /* if shCount >= 8 */
10075   if (shCount >= 8) {
10076     shCount -= 8 ;
10077     if (shCount)
10078       shiftR1Left2Result(left, MSB16, result, LSB,
10079                          shCount, sign);
10080     else
10081       movLeft2Result(left, MSB16, result, LSB);
10082
10083     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
10084
10085     if(sign) {
10086       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10087       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
10088     }
10089   }
10090
10091   /*  1 <= shCount <= 7 */
10092   else
10093     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
10094 }
10095
10096 /*-----------------------------------------------------------------*/
10097 /* shiftRLong - shift right one long from left to result           */
10098 /* offl = LSB or MSB16                                             */
10099 /*-----------------------------------------------------------------*/
10100 static void shiftRLong (operand *left, int offl,
10101                         operand *result, int sign)
10102 {
10103     int size = AOP_SIZE(result);
10104     int same = pic16_sameRegs(AOP(left),AOP(result));
10105     int i;
10106     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10107
10108         if (same && (offl == MSB16)) { //shift one byte right
10109                 for(i=MSB16;i<size;i++) {
10110                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10111                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10112                 }
10113         }
10114
10115     if(sign)
10116                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10117         else
10118                 emitCLRC;
10119
10120         if (same) {
10121                 if (offl == LSB)
10122                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10123         } else {
10124         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10125         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10126         }
10127
10128     if(offl == MSB16) {
10129         /* add sign of "a" */
10130         pic16_addSign(result, MSB32, sign);
10131         }
10132
10133         if (same) {
10134         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10135         } else {
10136         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10137         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10138         }
10139         
10140         if (same) {
10141         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10142         } else {
10143         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10144         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10145         }
10146
10147         if (same) {
10148         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10149         } else {
10150         if(offl == LSB){
10151                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10152                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10153         }
10154         }
10155 }
10156
10157 /*-----------------------------------------------------------------*/
10158 /* genrshFour - shift four byte by a known amount != 0             */
10159 /*-----------------------------------------------------------------*/
10160 static void genrshFour (operand *result, operand *left,
10161                         int shCount, int sign)
10162 {
10163   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10164   /* if shifting more that 3 bytes */
10165   if(shCount >= 24 ) {
10166     shCount -= 24;
10167     if(shCount)
10168       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10169     else
10170       movLeft2Result(left, MSB32, result, LSB);
10171
10172     pic16_addSign(result, MSB16, sign);
10173   }
10174   else if(shCount >= 16){
10175     shCount -= 16;
10176     if(shCount)
10177       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10178     else{
10179       movLeft2Result(left, MSB24, result, LSB);
10180       movLeft2Result(left, MSB32, result, MSB16);
10181     }
10182     pic16_addSign(result, MSB24, sign);
10183   }
10184   else if(shCount >= 8){
10185     shCount -= 8;
10186     if(shCount == 1)
10187       shiftRLong(left, MSB16, result, sign);
10188     else if(shCount == 0){
10189       movLeft2Result(left, MSB16, result, LSB);
10190       movLeft2Result(left, MSB24, result, MSB16);
10191       movLeft2Result(left, MSB32, result, MSB24);
10192       pic16_addSign(result, MSB32, sign);
10193     }
10194     else{ //shcount >= 2
10195       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10196       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10197       /* the last shift is signed */
10198       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10199       pic16_addSign(result, MSB32, sign);
10200     }
10201   }
10202   else{   /* 1 <= shCount <= 7 */
10203     if(shCount <= 2){
10204       shiftRLong(left, LSB, result, sign);
10205       if(shCount == 2)
10206         shiftRLong(result, LSB, result, sign);
10207     }
10208     else{
10209       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10210       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10211       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10212     }
10213   }
10214 }
10215
10216 /*-----------------------------------------------------------------*/
10217 /* genRightShiftLiteral - right shifting by known count            */
10218 /*-----------------------------------------------------------------*/
10219 static void genRightShiftLiteral (operand *left,
10220                                   operand *right,
10221                                   operand *result,
10222                                   iCode *ic,
10223                                   int sign)
10224 {    
10225   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10226   int lsize,res_size;
10227
10228   pic16_freeAsmop(right,NULL,ic,TRUE);
10229
10230   pic16_aopOp(left,ic,FALSE);
10231   pic16_aopOp(result,ic,FALSE);
10232
10233   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10234
10235 #if VIEW_SIZE
10236   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10237                  AOP_SIZE(left));
10238 #endif
10239
10240   lsize = pic16_getDataSize(left);
10241   res_size = pic16_getDataSize(result);
10242   /* test the LEFT size !!! */
10243
10244   /* I suppose that the left size >= result size */
10245   if(shCount == 0){
10246     while(res_size--)
10247       movLeft2Result(left, lsize, result, res_size);
10248   }
10249
10250   else if(shCount >= (lsize * 8)){
10251
10252     if(res_size == 1) {
10253       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10254       if(sign) {
10255         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10256         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10257       }
10258     } else {
10259
10260       if(sign) {
10261         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10262         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10263         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10264         while(res_size--)
10265           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10266
10267       } else {
10268
10269         while(res_size--)
10270           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10271       }
10272     }
10273   } else {
10274
10275     switch (res_size) {
10276     case 1:
10277       genrshOne (result,left,shCount,sign);
10278       break;
10279
10280     case 2:
10281       genrshTwo (result,left,shCount,sign);
10282       break;
10283
10284     case 4:
10285       genrshFour (result,left,shCount,sign);
10286       break;
10287     default :
10288       break;
10289     }
10290
10291   }
10292
10293   pic16_freeAsmop(left,NULL,ic,TRUE);
10294   pic16_freeAsmop(result,NULL,ic,TRUE);
10295 }
10296
10297 #if !(USE_GENERIC_SIGNED_SHIFT)
10298 /*-----------------------------------------------------------------*/
10299 /* genSignedRightShift - right shift of signed number              */
10300 /*-----------------------------------------------------------------*/
10301 static void genSignedRightShift (iCode *ic)
10302 {
10303   operand *right, *left, *result;
10304   int size, offset;
10305   //  char *l;
10306   symbol *tlbl, *tlbl1 ;
10307   pCodeOp *pctemp;
10308
10309   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10310
10311   /* we do it the hard way put the shift count in b
10312      and loop thru preserving the sign */
10313   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10314
10315   right = IC_RIGHT(ic);
10316   left  = IC_LEFT(ic);
10317   result = IC_RESULT(ic);
10318
10319   pic16_aopOp(right,ic,FALSE);  
10320   pic16_aopOp(left,ic,FALSE);
10321   pic16_aopOp(result,ic,FALSE);
10322
10323
10324   if ( AOP_TYPE(right) == AOP_LIT) {
10325     genRightShiftLiteral (left,right,result,ic,1);
10326     return ;
10327   }
10328   /* shift count is unknown then we have to form 
10329      a loop get the loop count in B : Note: we take
10330      only the lower order byte since shifting
10331      more that 32 bits make no sense anyway, ( the
10332      largest size of an object can be only 32 bits ) */  
10333
10334   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10335   //pic16_emitcode("inc","b");
10336   //pic16_freeAsmop (right,NULL,ic,TRUE);
10337   //pic16_aopOp(left,ic,FALSE);
10338   //pic16_aopOp(result,ic,FALSE);
10339
10340   /* now move the left to the result if they are not the
10341      same */
10342   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10343       AOP_SIZE(result) > 1) {
10344
10345     size = AOP_SIZE(result);
10346     offset=0;
10347     while (size--) { 
10348       /*
10349         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10350         if (*l == '@' && IS_AOP_PREG(result)) {
10351
10352         pic16_emitcode("mov","a,%s",l);
10353         pic16_aopPut(AOP(result),"a",offset);
10354         } else
10355         pic16_aopPut(AOP(result),l,offset);
10356       */
10357       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10358       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10359
10360       offset++;
10361     }
10362   }
10363
10364   /* mov the highest order bit to OVR */    
10365   tlbl = newiTempLabel(NULL);
10366   tlbl1= newiTempLabel(NULL);
10367
10368   size = AOP_SIZE(result);
10369   offset = size - 1;
10370
10371   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10372
10373   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10374
10375   /* offset should be 0, 1 or 3 */
10376   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10377   emitSKPNZ;
10378   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10379
10380   pic16_emitpcode(POC_MOVWF, pctemp);
10381
10382
10383   pic16_emitpLabel(tlbl->key);
10384
10385   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10386   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10387
10388   while(--size) {
10389     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10390   }
10391
10392   pic16_emitpcode(POC_DECFSZ,  pctemp);
10393   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10394   pic16_emitpLabel(tlbl1->key);
10395
10396   pic16_popReleaseTempReg(pctemp,1);
10397 #if 0
10398   size = AOP_SIZE(result);
10399   offset = size - 1;
10400   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10401   pic16_emitcode("rlc","a");
10402   pic16_emitcode("mov","ov,c");
10403   /* if it is only one byte then */
10404   if (size == 1) {
10405     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10406     MOVA(l);
10407     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10408     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10409     pic16_emitcode("mov","c,ov");
10410     pic16_emitcode("rrc","a");
10411     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10412     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10413     pic16_aopPut(AOP(result),"a",0);
10414     goto release ;
10415   }
10416
10417   reAdjustPreg(AOP(result));
10418   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10419   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10420   pic16_emitcode("mov","c,ov");
10421   while (size--) {
10422     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10423     MOVA(l);
10424     pic16_emitcode("rrc","a");         
10425     pic16_aopPut(AOP(result),"a",offset--);
10426   }
10427   reAdjustPreg(AOP(result));
10428   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10429   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10430
10431  release:
10432 #endif
10433
10434   pic16_freeAsmop(left,NULL,ic,TRUE);
10435   pic16_freeAsmop(result,NULL,ic,TRUE);
10436   pic16_freeAsmop(right,NULL,ic,TRUE);
10437 }
10438 #endif
10439
10440 #if !(USE_GENERIC_SIGNED_SHIFT)
10441 #warning This implementation of genRightShift() is incomplete!
10442 /*-----------------------------------------------------------------*/
10443 /* genRightShift - generate code for right shifting                */
10444 /*-----------------------------------------------------------------*/
10445 static void genRightShift (iCode *ic)
10446 {
10447     operand *right, *left, *result;
10448     sym_link *letype ;
10449     int size, offset;
10450     char *l;
10451     symbol *tlbl, *tlbl1 ;
10452
10453     /* if signed then we do it the hard way preserve the
10454     sign bit moving it inwards */
10455     letype = getSpec(operandType(IC_LEFT(ic)));
10456     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10457
10458     if (!SPEC_USIGN(letype)) {
10459         genSignedRightShift (ic);
10460         return ;
10461     }
10462
10463     /* signed & unsigned types are treated the same : i.e. the
10464     signed is NOT propagated inwards : quoting from the
10465     ANSI - standard : "for E1 >> E2, is equivalent to division
10466     by 2**E2 if unsigned or if it has a non-negative value,
10467     otherwise the result is implementation defined ", MY definition
10468     is that the sign does not get propagated */
10469
10470     right = IC_RIGHT(ic);
10471     left  = IC_LEFT(ic);
10472     result = IC_RESULT(ic);
10473
10474     pic16_aopOp(right,ic,FALSE);
10475
10476     /* if the shift count is known then do it 
10477     as efficiently as possible */
10478     if (AOP_TYPE(right) == AOP_LIT) {
10479         genRightShiftLiteral (left,right,result,ic, 0);
10480         return ;
10481     }
10482
10483     /* shift count is unknown then we have to form 
10484     a loop get the loop count in B : Note: we take
10485     only the lower order byte since shifting
10486     more that 32 bits make no sense anyway, ( the
10487     largest size of an object can be only 32 bits ) */  
10488
10489     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10490     pic16_emitcode("inc","b");
10491     pic16_aopOp(left,ic,FALSE);
10492     pic16_aopOp(result,ic,FALSE);
10493
10494     /* now move the left to the result if they are not the
10495     same */
10496     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10497         AOP_SIZE(result) > 1) {
10498
10499         size = AOP_SIZE(result);
10500         offset=0;
10501         while (size--) {
10502             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10503             if (*l == '@' && IS_AOP_PREG(result)) {
10504
10505                 pic16_emitcode("mov","a,%s",l);
10506                 pic16_aopPut(AOP(result),"a",offset);
10507             } else
10508                 pic16_aopPut(AOP(result),l,offset);
10509             offset++;
10510         }
10511     }
10512
10513     tlbl = newiTempLabel(NULL);
10514     tlbl1= newiTempLabel(NULL);
10515     size = AOP_SIZE(result);
10516     offset = size - 1;
10517
10518     /* if it is only one byte then */
10519     if (size == 1) {
10520
10521       tlbl = newiTempLabel(NULL);
10522       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10523         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10524         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10525       }
10526
10527       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10528       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10529       pic16_emitpLabel(tlbl->key);
10530       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10531       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10532       emitSKPC;
10533       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10534
10535       goto release ;
10536     }
10537
10538     reAdjustPreg(AOP(result));
10539     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10540     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10541     CLRC;
10542     while (size--) {
10543         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10544         MOVA(l);
10545         pic16_emitcode("rrc","a");         
10546         pic16_aopPut(AOP(result),"a",offset--);
10547     }
10548     reAdjustPreg(AOP(result));
10549
10550     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10551     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10552
10553 release:
10554     pic16_freeAsmop(left,NULL,ic,TRUE);
10555     pic16_freeAsmop (right,NULL,ic,TRUE);
10556     pic16_freeAsmop(result,NULL,ic,TRUE);
10557 }
10558 #endif
10559
10560 #if (USE_GENERIC_SIGNED_SHIFT)
10561 /*-----------------------------------------------------------------*/
10562 /* genGenericShift - generates code for left or right shifting     */
10563 /*-----------------------------------------------------------------*/
10564 static void genGenericShift (iCode *ic, int isShiftLeft) {
10565   operand *left,*right, *result;
10566   int offset;
10567   int sign, signedCount;
10568   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10569   PIC_OPCODE pos_shift, neg_shift;
10570
10571   FENTRY;
10572
10573   right = IC_RIGHT(ic);
10574   left  = IC_LEFT(ic);
10575   result = IC_RESULT(ic);
10576
10577   pic16_aopOp(right,ic,FALSE);
10578   pic16_aopOp(left,ic,FALSE);
10579   pic16_aopOp(result,ic,FALSE);
10580
10581   sign = !SPEC_USIGN(operandType (left));
10582   signedCount = !SPEC_USIGN(operandType (right));
10583
10584   /* if the shift count is known then do it 
10585      as efficiently as possible */
10586   if (AOP_TYPE(right) == AOP_LIT) {
10587     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10588     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10589     // we should modify right->aopu.aop_lit here!
10590     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10591     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10592     if (isShiftLeft)
10593       pic16_genLeftShiftLiteral (left,right,result,ic);
10594     else
10595       genRightShiftLiteral (left,right,result,ic, sign);
10596
10597     goto release;
10598   } // if (right is literal)
10599
10600   /* shift count is unknown then we have to form a loop.
10601    * Note: we take only the lower order byte since shifting
10602    * more than 32 bits make no sense anyway, ( the
10603    * largest size of an object can be only 32 bits )
10604    * Note: we perform arithmetic shifts if the left operand is
10605    * signed and we do an (effective) right shift, i. e. we
10606    * shift in the sign bit from the left. */
10607    
10608   label_complete = newiTempLabel ( NULL );
10609   label_loop_pos = newiTempLabel ( NULL );
10610   label_loop_neg = NULL;
10611   label_negative = NULL;
10612   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10613   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10614
10615   if (signedCount) {
10616     // additional labels needed
10617     label_loop_neg = newiTempLabel ( NULL );
10618     label_negative = newiTempLabel ( NULL );
10619   } // if
10620
10621   // copy source to result -- this will effectively truncate the left operand to the size of result!
10622   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10623   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10624   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10625     mov2f (AOP(result),AOP(left), offset);
10626   } // for
10627
10628   // if result is longer than left, fill with zeros (or sign)
10629   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10630     if (sign && AOP_SIZE(left) > 0) {
10631       // shift signed operand -- fill with sign
10632       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10633       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10634       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10635       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10636         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10637       } // for
10638     } else {
10639       // shift unsigned operand -- fill result with zeros
10640       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10641         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10642       } // for
10643     }
10644   } // if (size mismatch)
10645
10646   pic16_mov2w (AOP(right), 0);
10647   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10648   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10649   
10650 #if 0
10651   // perform a shift by one (shift count is positive)
10652   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10653   // 2n+[2,3]+({1,3}+n+3)c-2+[0,2]=({4,6}+n)c+2n+[0,3]          ({5,7}c+[2,5] / {6,8}c+[4, 7] / {8,10}c+[ 8,11])
10654   pic16_emitpLabel (label_loop_pos->key);
10655   emitCLRC;
10656   if (sign && (pos_shift == POC_RRCF)) {
10657     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10658     emitSETC;
10659   } // if
10660   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10661   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10662   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10663 #else
10664   // perform a shift by one (shift count is positive)
10665   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10666   // 2n+[2,3]+2+({0,2}+n+3)c-1+[0,2]=({3,5}+n)c+2n+[3,6]        ({4,6}c+[5,8] / {5,7}c+[7,10] / {7, 9}c+[11,14])
10667   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10668   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10669   emitCLRC;
10670   pic16_emitpLabel (label_loop_pos->key);
10671   if (sign && (pos_shift == POC_RRCF)) {
10672     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10673     emitSETC;
10674   } // if
10675   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10676   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10677   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10678   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10679 #endif
10680
10681   if (signedCount) {
10682     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10683
10684     pic16_emitpLabel (label_negative->key);
10685     // perform a shift by -1 (shift count is negative)
10686     // 2n+4+1+({0,2}+n+3)*c-1=({3,5}+n)c+2n+4                   ({4,6}c+6 / {5,7}c+8 / {7,9}c+12)
10687     emitCLRC;
10688     pic16_emitpLabel (label_loop_neg->key);
10689     if (sign && (neg_shift == POC_RRCF)) {
10690       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10691       emitSETC;
10692     } // if
10693     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10694     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10695     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10696     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10697   } // if (signedCount)
10698
10699   pic16_emitpLabel (label_complete->key);
10700
10701 release:
10702   pic16_freeAsmop (right,NULL,ic,TRUE);
10703   pic16_freeAsmop(left,NULL,ic,TRUE);
10704   pic16_freeAsmop(result,NULL,ic,TRUE);
10705 }
10706
10707 static void genLeftShift (iCode *ic) {
10708   genGenericShift (ic, 1);
10709 }
10710
10711 static void genRightShift (iCode *ic) {
10712   genGenericShift (ic, 0);
10713 }
10714 #endif
10715
10716
10717 void pic16_loadFSR0(operand *op)
10718 {
10719         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10720 }
10721
10722 /*-----------------------------------------------------------------*/
10723 /* genUnpackBits - generates code for unpacking bits               */
10724 /*-----------------------------------------------------------------*/
10725 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10726 {    
10727   int shCnt ;
10728   int rlen = 0 ;
10729   sym_link *etype, *letype;
10730   int blen=0, bstr=0;
10731   int lbstr;
10732   int offset = 0 ;
10733
10734     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10735     etype = getSpec(operandType(result));
10736     letype = getSpec(operandType(left));
10737     
10738 //    if(IS_BITFIELD(etype)) {
10739       blen = SPEC_BLEN(etype);
10740       bstr = SPEC_BSTR(etype);
10741 //    }
10742
10743     lbstr = SPEC_BSTR( letype );
10744
10745 #if 1
10746     if((blen == 1) && (bstr < 8)) {
10747       /* it is a single bit, so use the appropriate bit instructions */
10748       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10749
10750       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10751       
10752       if((ptype == POINTER) && (result)) {
10753         /* workaround to reduce the extra lfsr instruction */
10754         pic16_emitpcode(POC_BTFSC,
10755               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10756       } else {
10757         pic16_emitpcode(POC_BTFSC,
10758               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10759       }
10760         
10761       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10762
10763       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10764       return;
10765     }
10766
10767 #endif
10768
10769         /* the following call to pic16_loadFSR0 is temporary until
10770          * optimization to handle single bit assignments is added
10771          * to the function. Until then use the old safe way! -- VR */
10772         pic16_loadFSR0( left );
10773  
10774         /* read the first byte  */
10775         switch (ptype) {
10776                 case POINTER:
10777                 case IPOINTER:
10778                 case PPOINTER:
10779                 case FPOINTER:
10780                 case GPOINTER:
10781                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10782                         break;
10783                 case CPOINTER:
10784                         pic16_emitcode("clr","a");
10785                         pic16_emitcode("movc","a","@a+dptr");
10786                         break;
10787         }
10788         
10789
10790         /* if we have bitdisplacement then it fits   */
10791         /* into this byte completely or if length is */
10792         /* less than a byte                          */
10793         if ((shCnt = SPEC_BSTR(etype)) || 
10794                 (SPEC_BLEN(etype) <= 8))  {
10795
10796                 /* shift right acc */
10797                 AccRsh(shCnt, 0);
10798
10799                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10800                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10801
10802 /* VR -- normally I would use the following, but since we use the hack,
10803  * to avoid the masking from AccRsh, why not mask it right now? */
10804
10805 /*
10806                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10807 */
10808
10809                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10810           return ;
10811         }
10812
10813
10814
10815         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10816         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10817         exit(-1);
10818
10819     /* bit field did not fit in a byte  */
10820     rlen = SPEC_BLEN(etype) - 8;
10821     pic16_aopPut(AOP(result),"a",offset++);
10822
10823     while (1)  {
10824
10825         switch (ptype) {
10826         case POINTER:
10827         case IPOINTER:
10828             pic16_emitcode("inc","%s",rname);
10829             pic16_emitcode("mov","a,@%s",rname);
10830             break;
10831             
10832         case PPOINTER:
10833             pic16_emitcode("inc","%s",rname);
10834             pic16_emitcode("movx","a,@%s",rname);
10835             break;
10836
10837         case FPOINTER:
10838             pic16_emitcode("inc","dptr");
10839             pic16_emitcode("movx","a,@dptr");
10840             break;
10841             
10842         case CPOINTER:
10843             pic16_emitcode("clr","a");
10844             pic16_emitcode("inc","dptr");
10845             pic16_emitcode("movc","a","@a+dptr");
10846             break;
10847             
10848         case GPOINTER:
10849             pic16_emitcode("inc","dptr");
10850             pic16_emitcode("lcall","__gptrget");
10851             break;
10852         }
10853
10854         rlen -= 8;            
10855         /* if we are done */
10856         if ( rlen <= 0 )
10857             break ;
10858         
10859         pic16_aopPut(AOP(result),"a",offset++);
10860                               
10861     }
10862     
10863     if (rlen) {
10864         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10865         pic16_aopPut(AOP(result),"a",offset);          
10866     }
10867     
10868     return ;
10869 }
10870
10871
10872 static void genDataPointerGet(operand *left,
10873                               operand *result,
10874                               iCode *ic)
10875 {
10876   int size, offset = 0, leoffset=0 ;
10877
10878         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10879         pic16_aopOp(result, ic, FALSE);
10880
10881         size = AOP_SIZE(result);
10882 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10883
10884
10885 #if 0
10886         /* The following tests may save a redudant movff instruction when
10887          * accessing unions */
10888          
10889         /* if they are the same */
10890         if (operandsEqu (left, result)) {
10891                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10892                 goto release;
10893         }
10894 #endif
10895
10896 #if 0
10897         /* if they are the same registers */
10898         if (pic16_sameRegs(AOP(left),AOP(result))) {
10899                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10900                 goto release;
10901         }
10902 #endif
10903
10904 #if 1
10905         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10906                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10907                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10908                 goto release;
10909         }
10910 #endif
10911
10912
10913 #if 0
10914         if ( AOP_TYPE(left) == AOP_PCODE) {
10915                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
10916                                 AOP(left)->aopu.pcop->name,
10917                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
10918                                 PCOR(AOP(left)->aopu.pcop)->instance:
10919                                 PCOI(AOP(left)->aopu.pcop)->offset);
10920         }
10921 #endif
10922
10923         if(AOP(left)->aopu.pcop->type == PO_DIR)
10924                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10925
10926         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10927
10928         while (size--) {
10929                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10930                 
10931                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
10932                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
10933                         pic16_mov2w(AOP(left), offset); // patch 8
10934                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10935                 } else {
10936                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10937                                 pic16_popGet(AOP(left), offset), //patch 8
10938                                 pic16_popGet(AOP(result), offset)));
10939                 }
10940
10941                 offset++;
10942                 leoffset++;
10943         }
10944
10945 release:
10946     pic16_freeAsmop(result,NULL,ic,TRUE);
10947 }
10948
10949
10950
10951 /*-----------------------------------------------------------------*/
10952 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10953 /*-----------------------------------------------------------------*/
10954 static void genNearPointerGet (operand *left, 
10955                                operand *result, 
10956                                iCode *ic)
10957 {
10958   asmop *aop = NULL;
10959   //regs *preg = NULL ;
10960   sym_link *rtype, *retype;
10961   sym_link *ltype = operandType(left);    
10962
10963     FENTRY;
10964     
10965     rtype = operandType(result);
10966     retype= getSpec(rtype);
10967     
10968     pic16_aopOp(left,ic,FALSE);
10969
10970 //    pic16_DumpOp("(left)",left);
10971 //    pic16_DumpOp("(result)",result);
10972
10973     /* if left is rematerialisable and
10974      * result is not bit variable type and
10975      * the left is pointer to data space i.e
10976      * lower 128 bytes of space */
10977     
10978     if (AOP_TYPE(left) == AOP_PCODE
10979       && !IS_BITFIELD(retype)
10980       && DCL_TYPE(ltype) == POINTER) {
10981
10982         genDataPointerGet (left,result,ic);
10983         pic16_freeAsmop(left, NULL, ic, TRUE);
10984         return ;
10985     }
10986     
10987     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10988
10989     /* if the value is already in a pointer register
10990      * then don't need anything more */
10991     if (!AOP_INPREG(AOP(left))) {
10992       /* otherwise get a free pointer register */
10993       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10994                 
10995       /* VR -- the whole concept is to load FSR0 with the address of the symbol */
10996       /* bitfields will be handled by genUnpackBits */
10997       if(!IS_BITFIELD(retype)) {
10998
10999         if(is_LitAOp( AOP(left) )) {
11000           pic16_loadFSR0( left );
11001         } else {
11002             // set up FSR0 with address from left
11003             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11004             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11005         }
11006       }
11007     }
11008 //    else
11009 //    rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11010     
11011     pic16_aopOp (result,ic,FALSE);
11012     
11013     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11014
11015     /* if bitfield then unpack the bits */
11016     if (IS_BITFIELD(retype)) 
11017       genUnpackBits (result, left, NULL, POINTER);
11018     else {
11019       /* we have can just get the values */
11020       int size = AOP_SIZE(result);
11021       int offset = 0;   
11022         
11023       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11024
11025       /* fsr0 is loaded already -- VR */
11026 //      pic16_loadFSR0( left );
11027
11028 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
11029 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
11030       while(size--) {
11031         if(size) {
11032           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11033                 pic16_popGet(AOP(result), offset++)));
11034         } else {
11035           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11036                 pic16_popGet(AOP(result), offset++)));
11037         }
11038       }
11039 #if 0
11040 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
11041 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
11042       if(size)
11043         pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
11044 #endif
11045 /*
11046         while (size--) {
11047             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
11048
11049                 pic16_emitcode("mov","a,@%s",rname);
11050                 pic16_aopPut(AOP(result),"a",offset);
11051             } else {
11052                 sprintf(buffer,"@%s",rname);
11053                 pic16_aopPut(AOP(result),buffer,offset);
11054             }
11055             offset++ ;
11056             if (size)
11057                 pic16_emitcode("inc","%s",rname);
11058         }
11059 */
11060     }
11061
11062     /* now some housekeeping stuff */
11063     if (aop) {
11064       /* we had to allocate for this iCode */
11065       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11066       pic16_freeAsmop(NULL,aop,ic,TRUE);
11067     } else { 
11068       /* we did not allocate which means left
11069        * already in a pointer register, then
11070        * if size > 0 && this could be used again
11071        * we have to point it back to where it 
11072        * belongs */
11073       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11074       if (AOP_SIZE(result) > 1
11075         && !OP_SYMBOL(left)->remat
11076         && ( OP_SYMBOL(left)->liveTo > ic->seq
11077             || ic->depth )) {
11078 //        int size = AOP_SIZE(result) - 1;
11079 //        while (size--)
11080 //          pic16_emitcode("dec","%s",rname);
11081         }
11082     }
11083
11084     /* done */
11085     pic16_freeAsmop(left,NULL,ic,TRUE);
11086     pic16_freeAsmop(result,NULL,ic,TRUE);
11087 }
11088
11089 /*-----------------------------------------------------------------*/
11090 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
11091 /*-----------------------------------------------------------------*/
11092 static void genPagedPointerGet (operand *left, 
11093                                operand *result, 
11094                                iCode *ic)
11095 {
11096     asmop *aop = NULL;
11097     regs *preg = NULL ;
11098     char *rname ;
11099     sym_link *rtype, *retype;    
11100
11101     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11102
11103     rtype = operandType(result);
11104     retype= getSpec(rtype);
11105     
11106     pic16_aopOp(left,ic,FALSE);
11107
11108   /* if the value is already in a pointer register
11109        then don't need anything more */
11110     if (!AOP_INPREG(AOP(left))) {
11111         /* otherwise get a free pointer register */
11112         aop = newAsmop(0);
11113         preg = getFreePtr(ic,&aop,FALSE);
11114         pic16_emitcode("mov","%s,%s",
11115                 preg->name,
11116                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11117         rname = preg->name ;
11118     } else
11119         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11120     
11121     pic16_freeAsmop(left,NULL,ic,TRUE);
11122     pic16_aopOp (result,ic,FALSE);
11123
11124     /* if bitfield then unpack the bits */
11125     if (IS_BITFIELD(retype)) 
11126         genUnpackBits (result,left,rname,PPOINTER);
11127     else {
11128         /* we have can just get the values */
11129         int size = AOP_SIZE(result);
11130         int offset = 0 ;        
11131         
11132         while (size--) {
11133             
11134             pic16_emitcode("movx","a,@%s",rname);
11135             pic16_aopPut(AOP(result),"a",offset);
11136             
11137             offset++ ;
11138             
11139             if (size)
11140                 pic16_emitcode("inc","%s",rname);
11141         }
11142     }
11143
11144     /* now some housekeeping stuff */
11145     if (aop) {
11146         /* we had to allocate for this iCode */
11147         pic16_freeAsmop(NULL,aop,ic,TRUE);
11148     } else { 
11149         /* we did not allocate which means left
11150            already in a pointer register, then
11151            if size > 0 && this could be used again
11152            we have to point it back to where it 
11153            belongs */
11154         if (AOP_SIZE(result) > 1 &&
11155             !OP_SYMBOL(left)->remat &&
11156             ( OP_SYMBOL(left)->liveTo > ic->seq ||
11157               ic->depth )) {
11158             int size = AOP_SIZE(result) - 1;
11159             while (size--)
11160                 pic16_emitcode("dec","%s",rname);
11161         }
11162     }
11163
11164     /* done */
11165     pic16_freeAsmop(result,NULL,ic,TRUE);
11166     
11167         
11168 }
11169
11170 /*-----------------------------------------------------------------*/
11171 /* genFarPointerGet - gget value from far space                    */
11172 /*-----------------------------------------------------------------*/
11173 static void genFarPointerGet (operand *left,
11174                               operand *result, iCode *ic)
11175 {
11176     int size, offset ;
11177     sym_link *retype = getSpec(operandType(result));
11178
11179     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11180
11181     pic16_aopOp(left,ic,FALSE);
11182
11183     /* if the operand is already in dptr 
11184     then we do nothing else we move the value to dptr */
11185     if (AOP_TYPE(left) != AOP_STR) {
11186         /* if this is remateriazable */
11187         if (AOP_TYPE(left) == AOP_IMMD)
11188             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11189         else { /* we need to get it byte by byte */
11190             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11191             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11192             if (options.model == MODEL_FLAT24)
11193             {
11194                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11195             }
11196         }
11197     }
11198     /* so dptr know contains the address */
11199     pic16_freeAsmop(left,NULL,ic,TRUE);
11200     pic16_aopOp(result,ic,FALSE);
11201
11202     /* if bit then unpack */
11203     if (IS_BITFIELD(retype)) 
11204         genUnpackBits(result,left,"dptr",FPOINTER);
11205     else {
11206         size = AOP_SIZE(result);
11207         offset = 0 ;
11208
11209         while (size--) {
11210             pic16_emitcode("movx","a,@dptr");
11211             pic16_aopPut(AOP(result),"a",offset++);
11212             if (size)
11213                 pic16_emitcode("inc","dptr");
11214         }
11215     }
11216
11217     pic16_freeAsmop(result,NULL,ic,TRUE);
11218 }
11219 #if 0
11220 /*-----------------------------------------------------------------*/
11221 /* genCodePointerGet - get value from code space                  */
11222 /*-----------------------------------------------------------------*/
11223 static void genCodePointerGet (operand *left,
11224                                 operand *result, iCode *ic)
11225 {
11226     int size, offset ;
11227     sym_link *retype = getSpec(operandType(result));
11228
11229     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11230
11231     pic16_aopOp(left,ic,FALSE);
11232
11233     /* if the operand is already in dptr 
11234     then we do nothing else we move the value to dptr */
11235     if (AOP_TYPE(left) != AOP_STR) {
11236         /* if this is remateriazable */
11237         if (AOP_TYPE(left) == AOP_IMMD)
11238             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11239         else { /* we need to get it byte by byte */
11240             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11241             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11242             if (options.model == MODEL_FLAT24)
11243             {
11244                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11245             }
11246         }
11247     }
11248     /* so dptr know contains the address */
11249     pic16_freeAsmop(left,NULL,ic,TRUE);
11250     pic16_aopOp(result,ic,FALSE);
11251
11252     /* if bit then unpack */
11253     if (IS_BITFIELD(retype)) 
11254         genUnpackBits(result,left,"dptr",CPOINTER);
11255     else {
11256         size = AOP_SIZE(result);
11257         offset = 0 ;
11258
11259         while (size--) {
11260             pic16_emitcode("clr","a");
11261             pic16_emitcode("movc","a,@a+dptr");
11262             pic16_aopPut(AOP(result),"a",offset++);
11263             if (size)
11264                 pic16_emitcode("inc","dptr");
11265         }
11266     }
11267
11268     pic16_freeAsmop(result,NULL,ic,TRUE);
11269 }
11270 #endif
11271 #if 0
11272 /*-----------------------------------------------------------------*/
11273 /* genGenPointerGet - gget value from generic pointer space        */
11274 /*-----------------------------------------------------------------*/
11275 static void genGenPointerGet (operand *left,
11276                               operand *result, iCode *ic)
11277 {
11278   int size, offset, lit;
11279   sym_link *retype = getSpec(operandType(result));
11280
11281         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11282         pic16_aopOp(left,ic,FALSE);
11283         pic16_aopOp(result,ic,FALSE);
11284         size = AOP_SIZE(result);
11285
11286         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11287
11288         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11289
11290                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11291                 // load FSR0 from immediate
11292                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11293
11294 //              pic16_loadFSR0( left );
11295
11296                 offset = 0;
11297                 while(size--) {
11298                         if(size) {
11299                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11300                         } else {
11301                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11302                         }
11303                         offset++;
11304                 }
11305                 goto release;
11306
11307         }
11308         else { /* we need to get it byte by byte */
11309                 // set up FSR0 with address from left
11310                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11311                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11312
11313                 offset = 0 ;
11314
11315                 while(size--) {
11316                         if(size) {
11317                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11318                         } else {
11319                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11320                         }
11321                         offset++;
11322                 }
11323                 goto release;
11324         }
11325
11326   /* if bit then unpack */
11327         if (IS_BITFIELD(retype)) 
11328                 genUnpackBits(result,left,"BAD",GPOINTER);
11329
11330         release:
11331         pic16_freeAsmop(left,NULL,ic,TRUE);
11332         pic16_freeAsmop(result,NULL,ic,TRUE);
11333
11334 }
11335 #endif
11336
11337
11338 /*-----------------------------------------------------------------*/
11339 /* genGenPointerGet - gget value from generic pointer space        */
11340 /*-----------------------------------------------------------------*/
11341 static void genGenPointerGet (operand *left,
11342                               operand *result, iCode *ic)
11343 {
11344   int size, offset, lit;
11345   sym_link *retype = getSpec(operandType(result));
11346   char fgptrget[32];
11347
11348     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11349     pic16_aopOp(left,ic,FALSE);
11350     pic16_aopOp(result,ic,FALSE);
11351     size = AOP_SIZE(result);
11352
11353     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11354
11355     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11356
11357       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11358       // load FSR0 from immediate
11359       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11360
11361       werror(W_POSSBUG2, __FILE__, __LINE__);
11362
11363       offset = 0;
11364       while(size--) {
11365         if(size) {
11366           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11367         } else {
11368           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11369         }
11370         offset++;
11371       }
11372
11373       goto release;
11374
11375     } else { /* we need to get it byte by byte */
11376
11377       /* set up WREG:PRODL:FSR0L with address from left */
11378       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11379       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11380       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11381       
11382       switch( size ) {
11383         case 1: strcpy(fgptrget, "__gptrget1"); break;
11384         case 2: strcpy(fgptrget, "__gptrget2"); break;
11385         case 3: strcpy(fgptrget, "__gptrget3"); break;
11386         case 4: strcpy(fgptrget, "__gptrget4"); break;
11387         default:
11388           werror(W_POSSBUG2, __FILE__, __LINE__);
11389           abort();
11390       }
11391       
11392       pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11393       
11394       assignResultValue(result, 1);
11395       
11396       {
11397         symbol *sym;
11398
11399           sym = newSymbol( fgptrget, 0 );
11400           strcpy(sym->rname, fgptrget);
11401           checkAddSym(&externs, sym);
11402
11403 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11404       }
11405               
11406       goto release;
11407     }
11408
11409   /* if bit then unpack */
11410     if (IS_BITFIELD(retype)) 
11411       genUnpackBits(result,left,"BAD",GPOINTER);
11412
11413 release:
11414   pic16_freeAsmop(left,NULL,ic,TRUE);
11415   pic16_freeAsmop(result,NULL,ic,TRUE);
11416 }
11417
11418 /*-----------------------------------------------------------------*/
11419 /* genConstPointerGet - get value from const generic pointer space */
11420 /*-----------------------------------------------------------------*/
11421 static void genConstPointerGet (operand *left,
11422                                 operand *result, iCode *ic)
11423 {
11424   //sym_link *retype = getSpec(operandType(result));
11425   // symbol *albl = newiTempLabel(NULL);        // patch 15
11426   // symbol *blbl = newiTempLabel(NULL);        //
11427   // PIC_OPCODE poc;                            // patch 15
11428   int size;
11429   int offset = 0;
11430
11431   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11432   pic16_aopOp(left,ic,FALSE);
11433   pic16_aopOp(result,ic,TRUE);
11434   size = AOP_SIZE(result);
11435
11436   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11437
11438   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11439 #if 0                                                                   // patch 15
11440   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
11441   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
11442   pic16_emitpLabel(albl->key);
11443
11444   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
11445   
11446   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
11447   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
11448   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
11449   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
11450   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
11451
11452   pic16_emitpLabel(blbl->key);
11453
11454   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
11455 #endif                                                                  // patch 15
11456
11457
11458   // set up table pointer
11459   if( (AOP_TYPE(left) == AOP_PCODE) 
11460       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11461           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
11462     {
11463       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11464       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11465       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11466       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11467       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11468       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11469     }
11470   else
11471     {
11472       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11473       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11474       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11475     }
11476
11477
11478   while(size--)
11479     {
11480       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11481       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11482       offset++;
11483     }
11484     
11485   pic16_freeAsmop(left,NULL,ic,TRUE);
11486   pic16_freeAsmop(result,NULL,ic,TRUE);
11487
11488 }
11489
11490
11491 /*-----------------------------------------------------------------*/
11492 /* genPointerGet - generate code for pointer get                   */
11493 /*-----------------------------------------------------------------*/
11494 static void genPointerGet (iCode *ic)
11495 {
11496     operand *left, *result ;
11497     sym_link *type, *etype;
11498     int p_type;
11499
11500     FENTRY;
11501     
11502     left = IC_LEFT(ic);
11503     result = IC_RESULT(ic) ;
11504
11505     /* depending on the type of pointer we need to
11506     move it to the correct pointer register */
11507     type = operandType(left);
11508     etype = getSpec(type);
11509
11510 #if 0
11511     if (IS_PTR_CONST(type))
11512 #else
11513     if (IS_CODEPTR(type))
11514 #endif
11515       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11516
11517     /* if left is of type of pointer then it is simple */
11518     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11519         p_type = DCL_TYPE(type);
11520     else {
11521         /* we have to go by the storage class */
11522         p_type = PTR_TYPE(SPEC_OCLS(etype));
11523
11524         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11525
11526         if (SPEC_OCLS(etype)->codesp ) {
11527           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11528           //p_type = CPOINTER ; 
11529         }
11530         else
11531             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
11532               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11533                /*p_type = FPOINTER ;*/ 
11534             else
11535                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
11536                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11537 /*                  p_type = PPOINTER; */
11538                 else
11539                     if (SPEC_OCLS(etype) == idata )
11540                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11541 /*                      p_type = IPOINTER; */
11542                     else
11543                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11544 /*                      p_type = POINTER ; */
11545     }
11546
11547     /* now that we have the pointer type we assign
11548     the pointer values */
11549     switch (p_type) {
11550
11551     case POINTER:       
11552     case IPOINTER:
11553         genNearPointerGet (left,result,ic);
11554         break;
11555
11556     case PPOINTER:
11557         genPagedPointerGet(left,result,ic);
11558         break;
11559
11560     case FPOINTER:
11561         genFarPointerGet (left,result,ic);
11562         break;
11563
11564     case CPOINTER:
11565         genConstPointerGet (left,result,ic);
11566         //pic16_emitcodePointerGet (left,result,ic);
11567         break;
11568
11569     case GPOINTER:
11570 #if 0
11571       if (IS_PTR_CONST(type))
11572         genConstPointerGet (left,result,ic);
11573       else
11574 #endif
11575         genGenPointerGet (left,result,ic);
11576       break;
11577
11578     default:
11579       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11580               "genPointerGet: illegal pointer type");
11581     
11582     }
11583
11584 }
11585
11586 /*-----------------------------------------------------------------*/
11587 /* genPackBits - generates code for packed bit storage             */
11588 /*-----------------------------------------------------------------*/
11589 static void genPackBits (sym_link    *etype , operand *result,
11590                          operand *right ,
11591                          char *rname, int p_type)
11592 {
11593   int shCnt = 0 ;
11594   int offset = 0  ;
11595   int rLen = 0 ;
11596   int blen, bstr ;   
11597   sym_link *retype;
11598   char *l ;
11599
11600         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11601         blen = SPEC_BLEN(etype);
11602         bstr = SPEC_BSTR(etype);
11603
11604         retype = getSpec(operandType(right));
11605
11606         if(AOP_TYPE(right) == AOP_LIT) {
11607                 if((blen == 1) && (bstr < 8)) {
11608                   unsigned long lit;
11609                         /* it is a single bit, so use the appropriate bit instructions */
11610
11611                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11612
11613                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11614 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11615                         if((p_type == POINTER) && (result)) {
11616                                 /* workaround to reduce the extra lfsr instruction */
11617                                 if(lit) {
11618                                         pic16_emitpcode(POC_BSF,
11619                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11620                                 } else {
11621                                         pic16_emitpcode(POC_BCF,
11622                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11623                                 }
11624                         } else {
11625                                 pic16_loadFSR0( result );
11626                                 if(lit) {
11627                                         pic16_emitpcode(POC_BSF,
11628                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11629                                 } else {
11630                                         pic16_emitpcode(POC_BCF,
11631                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11632                                 }
11633                         }
11634         
11635                   return;
11636                 }
11637
11638                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11639                 offset++;
11640         } else
11641         if(IS_BITFIELD(retype) 
11642           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11643           && (blen == 1)) {
11644           int rblen, rbstr;
11645
11646             rblen = SPEC_BLEN( retype );
11647             rbstr = SPEC_BSTR( retype );
11648             
11649
11650             if(IS_BITFIELD(etype)) {
11651               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11652               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11653             } else {
11654               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11655             }
11656             
11657             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11658             
11659             if(IS_BITFIELD(etype)) {
11660               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11661             } else {
11662               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11663             }
11664
11665             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11666             
11667             return;
11668         } else
11669           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11670
11671         /* if the bit lenth is less than or    */
11672         /* it exactly fits a byte then         */
11673         if((shCnt=SPEC_BSTR(etype))
11674                 || SPEC_BLEN(etype) <= 8 )  {
11675
11676                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11677
11678                 /* shift left acc */
11679                 AccLsh(shCnt);
11680
11681                 /* using PRODL as a temporary register here */
11682                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11683
11684                 switch (p_type) {
11685                         case FPOINTER:
11686                         case POINTER:
11687                                 pic16_loadFSR0( result );
11688                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11689 //                              pic16_emitcode ("mov","b,a");
11690 //                              pic16_emitcode("mov","a,@%s",rname);
11691                                 break;
11692
11693                         case GPOINTER:
11694                                 werror(W_POSSBUG2, __FILE__, __LINE__);
11695                                 break;
11696
11697                 }
11698 #if 1
11699                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11700                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11701                                         (unsigned char)(0xff >> (8-bstr))) ));
11702                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
11703                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11704 #endif
11705
11706           return;
11707         }
11708
11709
11710         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11711         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11712         exit(-1);
11713
11714
11715     /* if we r done */
11716     if ( SPEC_BLEN(etype) <= 8 )
11717         return ;
11718
11719     pic16_emitcode("inc","%s",rname);
11720     rLen = SPEC_BLEN(etype) ;     
11721
11722
11723
11724     /* now generate for lengths greater than one byte */
11725     while (1) {
11726
11727         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
11728
11729         rLen -= 8 ;
11730         if (rLen <= 0 )
11731             break ;
11732
11733         switch (p_type) {
11734             case POINTER:
11735                 if (*l == '@') {
11736                     MOVA(l);
11737                     pic16_emitcode("mov","@%s,a",rname);
11738                 } else
11739                     pic16_emitcode("mov","@%s,%s",rname,l);
11740                 break;
11741
11742             case FPOINTER:
11743                 MOVA(l);
11744                 pic16_emitcode("movx","@dptr,a");
11745                 break;
11746
11747             case GPOINTER:
11748                 MOVA(l);
11749                 DEBUGpic16_emitcode(";lcall","__gptrput");
11750                 break;  
11751         }   
11752         pic16_emitcode ("inc","%s",rname);
11753     }
11754
11755     MOVA(l);
11756
11757     /* last last was not complete */
11758     if (rLen)   {
11759         /* save the byte & read byte */
11760         switch (p_type) {
11761             case POINTER:
11762                 pic16_emitcode ("mov","b,a");
11763                 pic16_emitcode("mov","a,@%s",rname);
11764                 break;
11765
11766             case FPOINTER:
11767                 pic16_emitcode ("mov","b,a");
11768                 pic16_emitcode("movx","a,@dptr");
11769                 break;
11770
11771             case GPOINTER:
11772                 pic16_emitcode ("push","b");
11773                 pic16_emitcode ("push","acc");
11774                 pic16_emitcode ("lcall","__gptrget");
11775                 pic16_emitcode ("pop","b");
11776                 break;
11777         }
11778
11779         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11780         pic16_emitcode ("orl","a,b");
11781     }
11782
11783     if (p_type == GPOINTER)
11784         pic16_emitcode("pop","b");
11785
11786     switch (p_type) {
11787
11788     case POINTER:
11789         pic16_emitcode("mov","@%s,a",rname);
11790         break;
11791         
11792     case FPOINTER:
11793         pic16_emitcode("movx","@dptr,a");
11794         break;
11795         
11796     case GPOINTER:
11797         DEBUGpic16_emitcode(";lcall","__gptrput");
11798         break;                  
11799     }
11800 }
11801 /*-----------------------------------------------------------------*/
11802 /* genDataPointerSet - remat pointer to data space                 */
11803 /*-----------------------------------------------------------------*/
11804 static void genDataPointerSet(operand *right,
11805                               operand *result,
11806                               iCode *ic)
11807 {
11808     int size, offset = 0, resoffset=0 ;
11809
11810     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11811     pic16_aopOp(right,ic,FALSE);
11812
11813     size = AOP_SIZE(right);
11814
11815 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11816
11817 #if 0
11818     if ( AOP_TYPE(result) == AOP_PCODE) {
11819       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11820               AOP(result)->aopu.pcop->name,
11821                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11822               PCOR(AOP(result)->aopu.pcop)->instance:
11823               PCOI(AOP(result)->aopu.pcop)->offset);
11824     }
11825 #endif
11826
11827         if(AOP(result)->aopu.pcop->type == PO_DIR)
11828                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11829
11830         while (size--) {
11831                 if (AOP_TYPE(right) == AOP_LIT) {
11832                   unsigned int lit;
11833
11834                     if(!IS_FLOAT(operandType( right )))
11835                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11836                     else {
11837                       union {
11838                         unsigned long lit_int;
11839                         float lit_float;
11840                       } info;
11841         
11842                         /* take care if literal is a float */
11843                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11844                         lit = info.lit_int;
11845                     }
11846
11847                     lit = lit >> (8*offset);
11848                     if(lit&0xff) {
11849                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11850                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11851                     } else {
11852                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11853                     }
11854                 } else {
11855                   pic16_mov2w(AOP(right), offset);
11856                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11857                 }
11858                 offset++;
11859                 resoffset++;
11860         }
11861
11862     pic16_freeAsmop(right,NULL,ic,TRUE);
11863 }
11864
11865
11866
11867 /*-----------------------------------------------------------------*/
11868 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11869 /*-----------------------------------------------------------------*/
11870 static void genNearPointerSet (operand *right,
11871                                operand *result, 
11872                                iCode *ic)
11873 {
11874   asmop *aop = NULL;
11875   char *l;
11876   sym_link *retype;
11877   sym_link *ptype = operandType(result);
11878   sym_link *resetype;
11879     
11880         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11881         retype= getSpec(operandType(right));
11882         resetype = getSpec(operandType(result));
11883   
11884         pic16_aopOp(result,ic,FALSE);
11885     
11886         /* if the result is rematerializable &
11887          * in data space & not a bit variable */
11888         
11889         /* and result is not a bit variable */
11890         if (AOP_TYPE(result) == AOP_PCODE
11891 //              && AOP_TYPE(result) == AOP_IMMD
11892                 && DCL_TYPE(ptype) == POINTER
11893                 && !IS_BITFIELD(retype)
11894                 && !IS_BITFIELD(resetype)) {
11895
11896                 genDataPointerSet (right,result,ic);
11897                 pic16_freeAsmop(result,NULL,ic,TRUE);
11898           return;
11899         }
11900
11901         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11902         pic16_aopOp(right,ic,FALSE);
11903         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11904
11905         /* if the value is already in a pointer register
11906          * then don't need anything more */
11907         if (!AOP_INPREG(AOP(result))) {
11908                 /* otherwise get a free pointer register */
11909                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11910
11911 //              if( (AOP_TYPE(result) == AOP_PCODE) 
11912 //                      && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
11913 //                              || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
11914                 if(is_LitAOp( AOP(result) ))
11915                 {
11916                   if(!IS_BITFIELD(resetype))
11917                         pic16_loadFSR0( result );  // patch 10
11918                 } else {
11919                   if(!IS_BITFIELD(resetype)) {
11920                         // set up FSR0 with address of result
11921                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11922                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11923                   }
11924                 }
11925
11926         }
11927 //      else
11928 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11929
11930         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11931
11932 //      pic16_loadFSR0( result );
11933
11934         /* if bitfield then unpack the bits */
11935         if (IS_BITFIELD(resetype)) {
11936                 genPackBits (resetype, result, right, NULL, POINTER);
11937         } else {
11938                 /* we have can just get the values */
11939           int size = AOP_SIZE(right);
11940           int offset = 0 ;    
11941
11942                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11943                 while (size--) {
11944                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11945                         if (*l == '@' ) {
11946                                 //MOVA(l);
11947                                 //pic16_emitcode("mov","@%s,a",rname);
11948                                 pic16_emitcode("movf","indf0,w ;1");
11949                         } else {
11950
11951                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
11952                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
11953                                         if (size) {                                                                     // 
11954                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
11955                                         } else {                                                                        // 
11956                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
11957                                         }                                                                               // 
11958                                 } else { // no literal                                                                  // 
11959                                         if(size) {                                                                      // 
11960                                                 pic16_emitpcode(POC_MOVFF,                                              // 
11961                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
11962                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
11963                                         } else {                                                                        // 
11964                                                 pic16_emitpcode(POC_MOVFF,                                              // 
11965                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
11966                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
11967                                         }                                                                               //
11968                                 }                                                                                       // patch 10
11969                         }
11970                         offset++;
11971                 }
11972         }
11973
11974         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11975         /* now some housekeeping stuff */
11976         if (aop) {
11977                 /* we had to allocate for this iCode */
11978                 pic16_freeAsmop(NULL,aop,ic,TRUE);
11979         } else { 
11980                 /* we did not allocate which means left
11981                  * already in a pointer register, then
11982                  * if size > 0 && this could be used again
11983                  * we have to point it back to where it 
11984                  * belongs */
11985                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11986                 if (AOP_SIZE(right) > 1
11987                         && !OP_SYMBOL(result)->remat
11988                         && ( OP_SYMBOL(result)->liveTo > ic->seq
11989                                 || ic->depth )) {
11990
11991                   int size = AOP_SIZE(right) - 1;
11992
11993                         while (size--)
11994                                 pic16_emitcode("decf","fsr0,f");
11995                         //pic16_emitcode("dec","%s",rname);
11996                 }
11997         }
11998
11999         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12000         /* done */
12001 //release:
12002         pic16_freeAsmop(right,NULL,ic,TRUE);
12003         pic16_freeAsmop(result,NULL,ic,TRUE);
12004 }
12005
12006 /*-----------------------------------------------------------------*/
12007 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
12008 /*-----------------------------------------------------------------*/
12009 static void genPagedPointerSet (operand *right,
12010                                operand *result, 
12011                                iCode *ic)
12012 {
12013     asmop *aop = NULL;
12014     regs *preg = NULL ;
12015     char *rname , *l;
12016     sym_link *retype;
12017        
12018     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12019
12020     retype= getSpec(operandType(right));
12021     
12022     pic16_aopOp(result,ic,FALSE);
12023     
12024     /* if the value is already in a pointer register
12025        then don't need anything more */
12026     if (!AOP_INPREG(AOP(result))) {
12027         /* otherwise get a free pointer register */
12028         aop = newAsmop(0);
12029         preg = getFreePtr(ic,&aop,FALSE);
12030         pic16_emitcode("mov","%s,%s",
12031                 preg->name,
12032                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12033         rname = preg->name ;
12034     } else
12035         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12036     
12037     pic16_freeAsmop(result,NULL,ic,TRUE);
12038     pic16_aopOp (right,ic,FALSE);
12039
12040     /* if bitfield then unpack the bits */
12041     if (IS_BITFIELD(retype)) 
12042         genPackBits (retype,result,right,rname,PPOINTER);
12043     else {
12044         /* we have can just get the values */
12045         int size = AOP_SIZE(right);
12046         int offset = 0 ;        
12047         
12048         while (size--) {
12049             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12050             
12051             MOVA(l);
12052             pic16_emitcode("movx","@%s,a",rname);
12053
12054             if (size)
12055                 pic16_emitcode("inc","%s",rname);
12056
12057             offset++;
12058         }
12059     }
12060     
12061     /* now some housekeeping stuff */
12062     if (aop) {
12063         /* we had to allocate for this iCode */
12064         pic16_freeAsmop(NULL,aop,ic,TRUE);
12065     } else { 
12066         /* we did not allocate which means left
12067            already in a pointer register, then
12068            if size > 0 && this could be used again
12069            we have to point it back to where it 
12070            belongs */
12071         if (AOP_SIZE(right) > 1 &&
12072             !OP_SYMBOL(result)->remat &&
12073             ( OP_SYMBOL(result)->liveTo > ic->seq ||
12074               ic->depth )) {
12075             int size = AOP_SIZE(right) - 1;
12076             while (size--)
12077                 pic16_emitcode("dec","%s",rname);
12078         }
12079     }
12080
12081     /* done */
12082     pic16_freeAsmop(right,NULL,ic,TRUE);
12083     
12084         
12085 }
12086
12087 /*-----------------------------------------------------------------*/
12088 /* genFarPointerSet - set value from far space                     */
12089 /*-----------------------------------------------------------------*/
12090 static void genFarPointerSet (operand *right,
12091                               operand *result, iCode *ic)
12092 {
12093     int size, offset ;
12094     sym_link *retype = getSpec(operandType(right));
12095
12096     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12097     pic16_aopOp(result,ic,FALSE);
12098
12099     /* if the operand is already in dptr 
12100     then we do nothing else we move the value to dptr */
12101     if (AOP_TYPE(result) != AOP_STR) {
12102         /* if this is remateriazable */
12103         if (AOP_TYPE(result) == AOP_IMMD)
12104             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12105         else { /* we need to get it byte by byte */
12106             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12107             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12108             if (options.model == MODEL_FLAT24)
12109             {
12110                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12111             }
12112         }
12113     }
12114     /* so dptr know contains the address */
12115     pic16_freeAsmop(result,NULL,ic,TRUE);
12116     pic16_aopOp(right,ic,FALSE);
12117
12118     /* if bit then unpack */
12119     if (IS_BITFIELD(retype)) 
12120         genPackBits(retype,result,right,"dptr",FPOINTER);
12121     else {
12122         size = AOP_SIZE(right);
12123         offset = 0 ;
12124
12125         while (size--) {
12126             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12127             MOVA(l);
12128             pic16_emitcode("movx","@dptr,a");
12129             if (size)
12130                 pic16_emitcode("inc","dptr");
12131         }
12132     }
12133
12134     pic16_freeAsmop(right,NULL,ic,TRUE);
12135 }
12136
12137 /*-----------------------------------------------------------------*/
12138 /* genGenPointerSet - set value from generic pointer space         */
12139 /*-----------------------------------------------------------------*/
12140 #if 0
12141 static void genGenPointerSet (operand *right,
12142                               operand *result, iCode *ic)
12143 {
12144         int i, size, offset, lit;
12145         sym_link *retype = getSpec(operandType(right));
12146
12147         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12148
12149         pic16_aopOp(result,ic,FALSE);
12150         pic16_aopOp(right,ic,FALSE);
12151         size = AOP_SIZE(right);
12152         offset = 0;
12153
12154         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12155
12156         /* if the operand is already in dptr 
12157                 then we do nothing else we move the value to dptr */
12158         if (AOP_TYPE(result) != AOP_STR) {
12159                 /* if this is remateriazable */
12160                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12161                 // WARNING: anythig until "else" is untested!
12162                 if (AOP_TYPE(result) == AOP_IMMD) {
12163                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12164                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12165                         // load FSR0 from immediate
12166                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12167                         offset = 0;
12168                         while(size--) {
12169                                 if(size) {
12170                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12171                                 } else {
12172                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12173                                 }
12174                                 offset++;
12175                         }
12176                         goto release;
12177                 }
12178                 else { /* we need to get it byte by byte */
12179                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12180                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12181
12182                         // set up FSR0 with address of result
12183                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12184                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12185
12186                         /* hack hack! see if this the FSR. If so don't load W */
12187                         if(AOP_TYPE(right) != AOP_ACC) {
12188
12189                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12190
12191                                 if(AOP_TYPE(right) == AOP_LIT)
12192                                 {
12193                                         // copy literal
12194                                         // note: pic16_popGet handles sign extension
12195                                         for(i=0;i<size;i++) {
12196                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12197                                                 if(i < size-1)
12198                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12199                                                 else
12200                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12201                                         }
12202                                 } else {
12203                                         // copy regs
12204
12205                                         for(i=0;i<size;i++) {
12206                                                 if(i < size-1)
12207                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12208                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12209                                                 else
12210                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12211                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12212                                         }
12213                                 }
12214                                 goto release;
12215                         } 
12216                         // right = ACC
12217                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12218                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12219                         goto release;
12220         } // if (AOP_TYPE(result) != AOP_IMMD)
12221
12222         } // if (AOP_TYPE(result) != AOP_STR)
12223         /* so dptr know contains the address */
12224
12225
12226         /* if bit then unpack */
12227         if (IS_BITFIELD(retype)) 
12228                 genPackBits(retype,result,right,"dptr",GPOINTER);
12229         else {
12230                 size = AOP_SIZE(right);
12231                 offset = 0 ;
12232
12233                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12234
12235                 // set up FSR0 with address of result
12236                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12237                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12238         
12239                 while (size--) {
12240                         if (AOP_TYPE(right) == AOP_LIT) {
12241                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12242                                 if (size) {
12243                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12244                                 } else {
12245                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12246                                 }
12247                         } else { // no literal
12248                                 if(size) {
12249                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12250                                 } else {
12251                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12252                                 }
12253                         }
12254                         offset++;
12255                 }
12256         }
12257
12258         release:
12259         pic16_freeAsmop(right,NULL,ic,TRUE);
12260         pic16_freeAsmop(result,NULL,ic,TRUE);
12261 }
12262 #endif
12263
12264 static void genGenPointerSet (operand *right,
12265                               operand *result, iCode *ic)
12266 {
12267   int size;
12268   sym_link *retype = getSpec(operandType(right));
12269   char fgptrput[32];
12270
12271     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12272
12273     pic16_aopOp(result,ic,FALSE);
12274     pic16_aopOp(right,ic,FALSE);
12275     size = AOP_SIZE(right);
12276
12277     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12278
12279
12280     /* if bit then unpack */
12281     if (IS_BITFIELD(retype)) {
12282 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12283       genPackBits(retype,result,right,"dptr",GPOINTER);
12284       goto release;
12285     }
12286
12287     size = AOP_SIZE(right);
12288
12289     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12290
12291
12292
12293     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12294
12295     /* value of right+0 is placed on stack, which will be retrieved
12296      * by the support function this restoring the stack. The important
12297      * thing is that there is no need to manually restore stack pointer
12298      * here */
12299     pushaop(AOP(right), 0);
12300 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12301     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12302     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12303     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12304     
12305     /* load address to write to in WREG:FSR0H:FSR0L */
12306     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12307                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12308     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12309                                 pic16_popCopyReg(&pic16_pc_prodl)));
12310     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12311     
12312
12313     /* put code here */
12314     switch (size) {
12315       case 1: strcpy(fgptrput, "__gptrput1"); break;
12316       case 2: strcpy(fgptrput, "__gptrput2"); break;
12317       case 3: strcpy(fgptrput, "__gptrput3"); break;
12318       case 4: strcpy(fgptrput, "__gptrput4"); break;
12319       default:
12320         werror(W_POSSBUG2, __FILE__, __LINE__);
12321         abort();
12322     }
12323     
12324     pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12325     
12326     {
12327       symbol *sym;
12328                   
12329         sym = newSymbol( fgptrput, 0 );
12330         strcpy(sym->rname, fgptrput);
12331         checkAddSym(&externs, sym);
12332     }
12333
12334 release:
12335     pic16_freeAsmop(right,NULL,ic,TRUE);
12336     pic16_freeAsmop(result,NULL,ic,TRUE);
12337 }
12338
12339 /*-----------------------------------------------------------------*/
12340 /* genPointerSet - stores the value into a pointer location        */
12341 /*-----------------------------------------------------------------*/
12342 static void genPointerSet (iCode *ic)
12343 {    
12344   operand *right, *result ;
12345   sym_link *type, *etype;
12346   int p_type;
12347
12348     FENTRY;
12349
12350     right = IC_RIGHT(ic);
12351     result = IC_RESULT(ic) ;
12352
12353     /* depending on the type of pointer we need to
12354     move it to the correct pointer register */
12355     type = operandType(result);
12356     etype = getSpec(type);
12357     /* if left is of type of pointer then it is simple */
12358     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12359         p_type = DCL_TYPE(type);
12360     }
12361     else {
12362         /* we have to go by the storage class */
12363         p_type = PTR_TYPE(SPEC_OCLS(etype));
12364
12365 /*      if (SPEC_OCLS(etype)->codesp ) { */
12366 /*          p_type = CPOINTER ;  */
12367 /*      } */
12368 /*      else */
12369 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12370 /*              p_type = FPOINTER ; */
12371 /*          else */
12372 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12373 /*                  p_type = PPOINTER ; */
12374 /*              else */
12375 /*                  if (SPEC_OCLS(etype) == idata ) */
12376 /*                      p_type = IPOINTER ; */
12377 /*                  else */
12378 /*                      p_type = POINTER ; */
12379     }
12380
12381     /* now that we have the pointer type we assign
12382     the pointer values */
12383     switch (p_type) {
12384
12385     case POINTER:
12386     case IPOINTER:
12387         genNearPointerSet (right,result,ic);
12388         break;
12389
12390     case PPOINTER:
12391         genPagedPointerSet (right,result,ic);
12392         break;
12393
12394     case FPOINTER:
12395         genFarPointerSet (right,result,ic);
12396         break;
12397
12398     case GPOINTER:
12399         genGenPointerSet (right,result,ic);
12400         break;
12401
12402     default:
12403       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12404               "genPointerSet: illegal pointer type");
12405     }
12406 }
12407
12408 /*-----------------------------------------------------------------*/
12409 /* genIfx - generate code for Ifx statement                        */
12410 /*-----------------------------------------------------------------*/
12411 static void genIfx (iCode *ic, iCode *popIc)
12412 {
12413   operand *cond = IC_COND(ic);
12414   int isbit =0;
12415
12416     FENTRY;
12417
12418     pic16_aopOp(cond,ic,FALSE);
12419
12420     /* get the value into acc */
12421     if (AOP_TYPE(cond) != AOP_CRY)
12422       pic16_toBoolean(cond);
12423     else
12424       isbit = 1;
12425     /* the result is now in the accumulator */
12426     pic16_freeAsmop(cond,NULL,ic,TRUE);
12427
12428     /* if there was something to be popped then do it */
12429     if (popIc)
12430       genIpop(popIc);
12431
12432     /* if the condition is  a bit variable */
12433     if (isbit && IS_ITEMP(cond) && 
12434         SPIL_LOC(cond)) {
12435       genIfxJump(ic,"c");
12436       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12437     } else {
12438       if (isbit && !IS_ITEMP(cond))
12439         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12440         else
12441         genIfxJump(ic,"a");
12442     }
12443     ic->generated = 1;
12444 }
12445
12446 /*-----------------------------------------------------------------*/
12447 /* genAddrOf - generates code for address of                       */
12448 /*-----------------------------------------------------------------*/
12449 static void genAddrOf (iCode *ic)
12450 {
12451   operand *result, *left;
12452   int size;
12453   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12454   pCodeOp *pcop0, *pcop1, *pcop2;
12455
12456     FENTRY;
12457
12458     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12459
12460     sym = OP_SYMBOL( IC_LEFT(ic) );
12461     
12462     if(sym->onStack) {
12463       /* get address of symbol on stack */
12464       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12465 #if 0
12466       fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12467                   OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12468 #endif
12469
12470       // operands on stack are accessible via "FSR2 + index" with index
12471       // starting at 2 for arguments and growing from 0 downwards for
12472       // local variables (index == 0 is not assigned so we add one here)
12473       {
12474         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12475         if (soffs <= 0) {
12476           assert (soffs < 0);
12477           soffs++;
12478         } // if
12479         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12480         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12481         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(&pic16_pc_fsr2l));
12482         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12483         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12484         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(&pic16_pc_fsr2h));
12485         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12486       }
12487
12488       goto release;
12489     }
12490         
12491 //      if(pic16_debug_verbose) {
12492 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12493 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12494 //      }
12495         
12496     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12497     size = AOP_SIZE(IC_RESULT(ic));
12498
12499
12500     /* Assume that what we want the address of is in data space
12501      * since there is no stack on the PIC, yet! -- VR */
12502   
12503     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12504     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12505     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12506         
12507     if (size == 3) {
12508       pic16_emitpcode(POC_MOVLW, pcop0);
12509       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12510       pic16_emitpcode(POC_MOVLW, pcop1);
12511       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12512       pic16_emitpcode(POC_MOVLW, pcop2);
12513       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12514     } else
12515     if (size == 2) {
12516       pic16_emitpcode(POC_MOVLW, pcop0);
12517       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12518       pic16_emitpcode(POC_MOVLW, pcop1);
12519     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12520     } else {
12521       pic16_emitpcode(POC_MOVLW, pcop0);
12522       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12523     }
12524
12525     pic16_freeAsmop(left, NULL, ic, FALSE);
12526 release:
12527     pic16_freeAsmop(result,NULL,ic,TRUE);
12528 }
12529
12530
12531 #if 0
12532 /*-----------------------------------------------------------------*/
12533 /* genFarFarAssign - assignment when both are in far space         */
12534 /*-----------------------------------------------------------------*/
12535 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12536 {
12537     int size = AOP_SIZE(right);
12538     int offset = 0;
12539     char *l ;
12540     /* first push the right side on to the stack */
12541     while (size--) {
12542         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12543         MOVA(l);
12544         pic16_emitcode ("push","acc");
12545     }
12546     
12547     pic16_freeAsmop(right,NULL,ic,FALSE);
12548     /* now assign DPTR to result */
12549     pic16_aopOp(result,ic,FALSE);
12550     size = AOP_SIZE(result);
12551     while (size--) {
12552         pic16_emitcode ("pop","acc");
12553         pic16_aopPut(AOP(result),"a",--offset);
12554     }
12555     pic16_freeAsmop(result,NULL,ic,FALSE);
12556         
12557 }
12558 #endif
12559
12560 /*-----------------------------------------------------------------*/
12561 /* genAssign - generate code for assignment                        */
12562 /*-----------------------------------------------------------------*/
12563 static void genAssign (iCode *ic)
12564 {
12565   operand *result, *right;
12566   int size, offset,know_W;
12567   unsigned long lit = 0L;
12568
12569   result = IC_RESULT(ic);
12570   right  = IC_RIGHT(ic) ;
12571
12572   FENTRY;
12573   
12574   /* if they are the same */
12575   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12576     return ;
12577
12578   /* reversed order operands are aopOp'ed so that result operand
12579    * is effective in case right is a stack symbol. This maneauver
12580    * allows to use the _G.resDirect flag later */
12581   pic16_aopOp(result,ic,TRUE);
12582   pic16_aopOp(right,ic,FALSE);
12583
12584   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12585
12586   /* if they are the same registers */
12587   if (pic16_sameRegs(AOP(right),AOP(result)))
12588     goto release;
12589
12590   /* if the result is a bit */
12591   if (AOP_TYPE(result) == AOP_CRY) {
12592     /* if the right size is a literal then
12593        we know what the value is */
12594     if (AOP_TYPE(right) == AOP_LIT) {
12595           
12596       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12597                   pic16_popGet(AOP(result),0));
12598
12599       if (((int) operandLitValue(right))) 
12600         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12601                        AOP(result)->aopu.aop_dir,
12602                        AOP(result)->aopu.aop_dir);
12603       else
12604         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12605                        AOP(result)->aopu.aop_dir,
12606                        AOP(result)->aopu.aop_dir);
12607       goto release;
12608     }
12609
12610     /* the right is also a bit variable */
12611     if (AOP_TYPE(right) == AOP_CRY) {
12612       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12613       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12614       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12615
12616       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12617                      AOP(result)->aopu.aop_dir,
12618                      AOP(result)->aopu.aop_dir);
12619       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12620                      AOP(right)->aopu.aop_dir,
12621                      AOP(right)->aopu.aop_dir);
12622       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12623                      AOP(result)->aopu.aop_dir,
12624                      AOP(result)->aopu.aop_dir);
12625       goto release ;
12626     }
12627
12628     /* we need to or */
12629     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12630     pic16_toBoolean(right);
12631     emitSKPZ;
12632     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12633     //pic16_aopPut(AOP(result),"a",0);
12634     goto release ;
12635   }
12636
12637   /* bit variables done */
12638   /* general case */
12639   size = AOP_SIZE(result);
12640   offset = 0 ;
12641
12642   if(AOP_TYPE(right) == AOP_LIT) {
12643         if(!IS_FLOAT(operandType( right )))
12644                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12645         else {
12646            union {
12647               unsigned long lit_int;
12648               float lit_float;
12649             } info;
12650         
12651                 /* take care if literal is a float */
12652                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12653                 lit = info.lit_int;
12654         }
12655   }
12656
12657 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12658 //                      sizeof(unsigned long int), sizeof(float));
12659
12660
12661   if (AOP_TYPE(right) == AOP_REG) {
12662     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12663     while (size--) {
12664       
12665       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12666     } // while
12667     goto release;
12668   }
12669
12670   if(AOP_TYPE(right) != AOP_LIT
12671         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12672         && !IS_FUNC(OP_SYM_TYPE(right))
12673         ) {
12674         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12675         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12676
12677         // set up table pointer
12678         if(is_LitOp(right)) {
12679 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12680                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12681                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12682                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12683                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12684                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12685                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12686         } else {
12687 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12688                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12689                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12690                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12691                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12692                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12693                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12694         }
12695
12696         size = min(AOP_SIZE(right), AOP_SIZE(result));
12697         while(size--) {
12698                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12699                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12700                         pic16_popGet(AOP(result),offset)));
12701                 offset++;
12702         }
12703
12704         if(AOP_SIZE(result) > AOP_SIZE(right)) {
12705                 size = AOP_SIZE(result) - AOP_SIZE(right);
12706                 while(size--) {
12707                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12708                         offset++;
12709                 }
12710         }
12711         goto release;
12712   }
12713
12714
12715
12716 #if 0
12717 /* VR - What is this?! */
12718   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12719     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12720     if(aopIdx(AOP(result),0) == 4) {
12721
12722       /* this is a workaround to save value of right into wreg too,
12723        * value of wreg is going to be used later */
12724       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12725       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12726       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12727       goto release;
12728     } else
12729 //      assert(0);
12730       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12731   }
12732 #endif
12733
12734   know_W=-1;
12735   while (size--) {
12736   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12737     if(AOP_TYPE(right) == AOP_LIT) {
12738       if(lit&0xff) {
12739         if(know_W != (lit&0xff))
12740           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12741         know_W = lit&0xff;
12742         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12743       } else
12744         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12745
12746       lit >>= 8;
12747
12748     } else if (AOP_TYPE(right) == AOP_CRY) {
12749       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12750       if(offset == 0) {
12751         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12752         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12753         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12754       }
12755     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12756         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12757         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12758     } else {
12759       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12760
12761       if(!_G.resDirect)         /* use this aopForSym feature */
12762         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12763     }
12764             
12765     offset++;
12766   }
12767   
12768  release:
12769   pic16_freeAsmop (right,NULL,ic,FALSE);
12770   pic16_freeAsmop (result,NULL,ic,TRUE);
12771 }   
12772
12773 /*-----------------------------------------------------------------*/
12774 /* genJumpTab - generates code for jump table                       */
12775 /*-----------------------------------------------------------------*/
12776 static void genJumpTab (iCode *ic)
12777 {
12778   symbol *jtab;
12779   char *l;
12780   pCodeOp *jt_offs;
12781   pCodeOp *jt_offs_hi;
12782   pCodeOp *jt_label;
12783
12784     FENTRY;
12785
12786     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12787     /* get the condition into accumulator */
12788     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12789     MOVA(l);
12790     /* multiply by three */
12791     pic16_emitcode("add","a,acc");
12792     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12793
12794     jtab = newiTempLabel(NULL);
12795     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12796     pic16_emitcode("jmp","@a+dptr");
12797     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12798
12799 #if 0
12800     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12801     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12802     emitSKPNC;
12803     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12804     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12805     pic16_emitpLabel(jtab->key);
12806
12807 #else
12808
12809     jt_offs = pic16_popGetTempReg(0);
12810     jt_offs_hi = pic16_popGetTempReg(1);
12811     jt_label = pic16_popGetLabel (jtab->key);
12812     //fprintf (stderr, "Creating jump table...\n");
12813
12814     // calculate offset into jump table (idx * sizeof (GOTO))
12815     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12816     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12817     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12818     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12819     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12820     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12821     pic16_emitpcode(POC_MOVWF , jt_offs);
12822
12823     // prepare PCLATx (set to first entry in jump table)
12824     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12825     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12826     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12827     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12828     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12829
12830     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12831     pic16_emitpcode(POC_ADDWF , jt_offs);
12832     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12833     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12834     emitSKPNC;
12835     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12836
12837     // release temporaries and prepare jump into table (new PCL --> WREG)
12838     pic16_emitpcode(POC_MOVFW , jt_offs);
12839     pic16_popReleaseTempReg (jt_offs_hi, 1);
12840     pic16_popReleaseTempReg (jt_offs, 0);
12841
12842     // jump into the table
12843     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12844
12845     pic16_emitpLabelFORCE(jtab->key);
12846
12847 #endif
12848     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12849
12850     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12851     /* now generate the jump labels */
12852     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12853          jtab = setNextItem(IC_JTLABELS(ic))) {
12854 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12855         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12856         
12857     }
12858     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12859
12860 }
12861
12862 /*-----------------------------------------------------------------*/
12863 /* genMixedOperation - gen code for operators between mixed types  */
12864 /*-----------------------------------------------------------------*/
12865 /*
12866   TSD - Written for the PIC port - but this unfortunately is buggy.
12867   This routine is good in that it is able to efficiently promote 
12868   types to different (larger) sizes. Unfortunately, the temporary
12869   variables that are optimized out by this routine are sometimes
12870   used in other places. So until I know how to really parse the 
12871   iCode tree, I'm going to not be using this routine :(.
12872 */
12873 static int genMixedOperation (iCode *ic)
12874 {
12875 #if 0
12876   operand *result = IC_RESULT(ic);
12877   sym_link *ctype = operandType(IC_LEFT(ic));
12878   operand *right = IC_RIGHT(ic);
12879   int ret = 0;
12880   int big,small;
12881   int offset;
12882
12883   iCode *nextic;
12884   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12885
12886   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12887
12888   nextic = ic->next;
12889   if(!nextic)
12890     return 0;
12891
12892   nextright = IC_RIGHT(nextic);
12893   nextleft  = IC_LEFT(nextic);
12894   nextresult = IC_RESULT(nextic);
12895
12896   pic16_aopOp(right,ic,FALSE);
12897   pic16_aopOp(result,ic,FALSE);
12898   pic16_aopOp(nextright,  nextic, FALSE);
12899   pic16_aopOp(nextleft,   nextic, FALSE);
12900   pic16_aopOp(nextresult, nextic, FALSE);
12901
12902   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12903
12904     operand *t = right;
12905     right = nextright;
12906     nextright = t; 
12907
12908     pic16_emitcode(";remove right +","");
12909
12910   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12911 /*
12912     operand *t = right;
12913     right = nextleft;
12914     nextleft = t; 
12915 */
12916     pic16_emitcode(";remove left +","");
12917   } else
12918     return 0;
12919
12920   big = AOP_SIZE(nextleft);
12921   small = AOP_SIZE(nextright);
12922
12923   switch(nextic->op) {
12924
12925   case '+':
12926     pic16_emitcode(";optimize a +","");
12927     /* if unsigned or not an integral type */
12928     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12929       pic16_emitcode(";add a bit to something","");
12930     } else {
12931
12932       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12933
12934       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12935         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12936         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12937       } else
12938         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12939
12940       offset = 0;
12941       while(--big) {
12942
12943         offset++;
12944
12945         if(--small) {
12946           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12947             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12948             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12949           }
12950
12951           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12952           emitSKPNC;
12953           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12954                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12955                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12956           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12957           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12958
12959         } else {
12960           pic16_emitcode("rlf","known_zero,w");
12961
12962           /*
12963             if right is signed
12964               btfsc  right,7
12965                addlw ff
12966           */
12967           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12968             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12969             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12970           } else {
12971             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12972           }
12973         }
12974       }
12975       ret = 1;
12976     }
12977   }
12978   ret = 1;
12979
12980 release:
12981   pic16_freeAsmop(right,NULL,ic,TRUE);
12982   pic16_freeAsmop(result,NULL,ic,TRUE);
12983   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12984   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12985   if(ret)
12986     nextic->generated = 1;
12987
12988   return ret;
12989 #else
12990   return 0;
12991 #endif
12992 }
12993 /*-----------------------------------------------------------------*/
12994 /* genCast - gen code for casting                                  */
12995 /*-----------------------------------------------------------------*/
12996 static void genCast (iCode *ic)
12997 {
12998   operand *result = IC_RESULT(ic);
12999   sym_link *ctype = operandType(IC_LEFT(ic));
13000   sym_link *rtype = operandType(IC_RIGHT(ic));
13001   sym_link *restype = operandType(IC_RESULT(ic));
13002   operand *right = IC_RIGHT(ic);
13003   int size, offset ;
13004
13005
13006     FENTRY;
13007
13008         /* if they are equivalent then do nothing */
13009 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13010 //              return ;
13011
13012         pic16_aopOp(right,ic,FALSE) ;
13013         pic16_aopOp(result,ic,FALSE);
13014
13015         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13016
13017
13018         /* if the result is a bit */
13019         if (AOP_TYPE(result) == AOP_CRY) {
13020         
13021                 /* if the right size is a literal then
13022                  * we know what the value is */
13023                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13024
13025                 if (AOP_TYPE(right) == AOP_LIT) {
13026                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13027                                 pic16_popGet(AOP(result),0));
13028
13029                         if (((int) operandLitValue(right))) 
13030                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13031                                         AOP(result)->aopu.aop_dir,
13032                                         AOP(result)->aopu.aop_dir);
13033                         else
13034                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13035                                         AOP(result)->aopu.aop_dir,
13036                                         AOP(result)->aopu.aop_dir);
13037                         goto release;
13038                 }
13039
13040                 /* the right is also a bit variable */
13041                 if (AOP_TYPE(right) == AOP_CRY) {
13042                         emitCLRC;
13043                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13044
13045                         pic16_emitcode("clrc","");
13046                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13047                                 AOP(right)->aopu.aop_dir,
13048                                 AOP(right)->aopu.aop_dir);
13049                         pic16_aopPut(AOP(result),"c",0);
13050                         goto release ;
13051                 }
13052
13053                 /* we need to or */
13054                 if (AOP_TYPE(right) == AOP_REG) {
13055                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
13056                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13057                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
13058                 }
13059                 pic16_toBoolean(right);
13060                 pic16_aopPut(AOP(result),"a",0);
13061                 goto release ;
13062         }
13063
13064         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13065           int offset = 1;
13066
13067                 size = AOP_SIZE(result);
13068
13069                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13070
13071                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
13072                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13073                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
13074
13075                 while (size--)
13076                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13077
13078                 goto release;
13079         }
13080
13081         if(IS_BITFIELD(getSpec(restype))
13082           && IS_BITFIELD(getSpec(rtype))) {
13083           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13084         }
13085
13086         /* if they are the same size : or less */
13087         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13088
13089                 /* if they are in the same place */
13090                 if (pic16_sameRegs(AOP(right),AOP(result)))
13091                         goto release;
13092
13093                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13094 #if 0
13095                 if (IS_PTR_CONST(rtype))
13096 #else
13097                 if (IS_CODEPTR(rtype))
13098 #endif
13099                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13100
13101 #if 0
13102                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13103 #else
13104                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13105 #endif
13106                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13107
13108 #if 0
13109                 if(AOP_TYPE(right) == AOP_IMMD) {
13110                   pCodeOp *pcop0, *pcop1, *pcop2;
13111                   symbol *sym = OP_SYMBOL( right );
13112
13113                         size = AOP_SIZE(result);
13114                         /* low */
13115                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13116                         /* high */
13117                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13118                         /* upper */
13119                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13120         
13121                         if (size == 3) {
13122                                 pic16_emitpcode(POC_MOVLW, pcop0);
13123                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13124                                 pic16_emitpcode(POC_MOVLW, pcop1);
13125                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13126                                 pic16_emitpcode(POC_MOVLW, pcop2);
13127                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13128                         } else
13129                         if (size == 2) {
13130                                 pic16_emitpcode(POC_MOVLW, pcop0);
13131                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13132                                 pic16_emitpcode(POC_MOVLW, pcop1);
13133                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13134                         } else {
13135                                 pic16_emitpcode(POC_MOVLW, pcop0);
13136                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13137                         }
13138                 } else
13139 #endif
13140                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13141                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13142                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13143                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13144                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13145                         if(AOP_SIZE(result) <2)
13146                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13147                 } else {
13148                         /* if they in different places then copy */
13149                         size = AOP_SIZE(result);
13150                         offset = 0 ;
13151                         while (size--) {
13152                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13153                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13154                                 offset++;
13155                         }
13156                 }
13157                 goto release;
13158         }
13159
13160         /* if the result is of type pointer */
13161         if (IS_PTR(ctype)) {
13162           int p_type;
13163           sym_link *type = operandType(right);
13164           sym_link *etype = getSpec(type);
13165
13166                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13167
13168                 /* pointer to generic pointer */
13169                 if (IS_GENPTR(ctype)) {
13170                   char *l = zero;
13171             
13172                         if (IS_PTR(type)) 
13173                                 p_type = DCL_TYPE(type);
13174                         else {
13175                 /* we have to go by the storage class */
13176                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13177
13178 /*              if (SPEC_OCLS(etype)->codesp )  */
13179 /*                  p_type = CPOINTER ;  */
13180 /*              else */
13181 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13182 /*                      p_type = FPOINTER ; */
13183 /*                  else */
13184 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13185 /*                          p_type = PPOINTER; */
13186 /*                      else */
13187 /*                          if (SPEC_OCLS(etype) == idata ) */
13188 /*                              p_type = IPOINTER ; */
13189 /*                          else */
13190 /*                              p_type = POINTER ; */
13191             }
13192                 
13193             /* the first two bytes are known */
13194       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13195             size = GPTRSIZE - 1; 
13196             offset = 0 ;
13197             while (size--) {
13198               if(offset < AOP_SIZE(right)) {
13199                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13200                 mov2f(AOP(result), AOP(right), offset);
13201 /*
13202                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13203                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13204                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13205                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13206                 } else { 
13207                   
13208                   pic16_aopPut(AOP(result),
13209                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13210                          offset);
13211                 }
13212 */
13213               } else 
13214                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13215               offset++;
13216             }
13217             /* the last byte depending on type */
13218             switch (p_type) {
13219             case IPOINTER:
13220             case POINTER:
13221                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13222                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13223 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13224                 break;
13225
13226             case CPOINTER:
13227                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13228                 break;
13229
13230             case FPOINTER:
13231               pic16_emitcode(";BUG!? ","%d",__LINE__);
13232                 l = one;
13233                 break;
13234             case PPOINTER:
13235               pic16_emitcode(";BUG!? ","%d",__LINE__);
13236                 l = "#0x03";
13237                 break;
13238
13239             case GPOINTER:
13240               pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13241               break;
13242               
13243             default:
13244                 /* this should never happen */
13245                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13246                        "got unknown pointer type");
13247                 exit(1);
13248             }
13249             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13250             goto release ;
13251         }
13252         
13253         /* just copy the pointers */
13254         size = AOP_SIZE(result);
13255         offset = 0 ;
13256         while (size--) {
13257             pic16_aopPut(AOP(result),
13258                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13259                    offset);
13260             offset++;
13261         }
13262         goto release ;
13263     }
13264     
13265
13266
13267     /* so we now know that the size of destination is greater
13268     than the size of the source.
13269     Now, if the next iCode is an operator then we might be
13270     able to optimize the operation without performing a cast.
13271     */
13272     if(genMixedOperation(ic))
13273       goto release;
13274
13275     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13276     
13277     /* we move to result for the size of source */
13278     size = AOP_SIZE(right);
13279     offset = 0 ;
13280     while (size--) {
13281       mov2f(AOP(result), AOP(right), offset);
13282       offset++;
13283     }
13284
13285     /* now depending on the sign of the destination */
13286     size = AOP_SIZE(result) - AOP_SIZE(right);
13287     /* if unsigned or not an integral type */
13288     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13289       while (size--)
13290         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13291     } else {
13292       /* we need to extend the sign :( */
13293
13294       if(size == 1) {
13295         /* Save one instruction of casting char to int */
13296         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13297         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13298         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
13299       } else {
13300         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13301
13302         if(offset)
13303           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13304         else
13305           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13306         
13307         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13308
13309         while (size--)
13310           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13311       }
13312     }
13313
13314 release:
13315     pic16_freeAsmop(right,NULL,ic,TRUE);
13316     pic16_freeAsmop(result,NULL,ic,TRUE);
13317
13318 }
13319
13320 /*-----------------------------------------------------------------*/
13321 /* genDjnz - generate decrement & jump if not zero instrucion      */
13322 /*-----------------------------------------------------------------*/
13323 static int genDjnz (iCode *ic, iCode *ifx)
13324 {
13325     symbol *lbl, *lbl1;
13326     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13327
13328     if (!ifx)
13329         return 0;
13330     
13331     /* if the if condition has a false label
13332        then we cannot save */
13333     if (IC_FALSE(ifx))
13334         return 0;
13335
13336     /* if the minus is not of the form 
13337        a = a - 1 */
13338     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13339         !IS_OP_LITERAL(IC_RIGHT(ic)))
13340         return 0;
13341
13342     if (operandLitValue(IC_RIGHT(ic)) != 1)
13343         return 0;
13344
13345     /* if the size of this greater than one then no
13346        saving */
13347     if (getSize(operandType(IC_RESULT(ic))) > 1)
13348         return 0;
13349
13350     /* otherwise we can save BIG */
13351     lbl = newiTempLabel(NULL);
13352     lbl1= newiTempLabel(NULL);
13353
13354     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13355     
13356     if (IS_AOP_PREG(IC_RESULT(ic))) {
13357         pic16_emitcode("dec","%s",
13358                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13359         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13360         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13361     } else {    
13362
13363
13364       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13365       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13366
13367       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13368       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13369
13370     }
13371     
13372     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13373     ifx->generated = 1;
13374     return 1;
13375 }
13376
13377 /*-----------------------------------------------------------------*/
13378 /* genReceive - generate code for a receive iCode                  */
13379 /*-----------------------------------------------------------------*/
13380 static void genReceive (iCode *ic)
13381 {    
13382
13383   FENTRY;
13384
13385 #if 0
13386   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13387         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13388 #endif
13389 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13390
13391   if (isOperandInFarSpace(IC_RESULT(ic))
13392       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13393           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13394
13395     int size = getSize(operandType(IC_RESULT(ic)));
13396     int offset =  pic16_fReturnSizePic - size;
13397
13398       assert( 0 );
13399       while (size--) {
13400         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13401                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13402                       offset++;
13403         }
13404
13405       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13406
13407       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13408       size = AOP_SIZE(IC_RESULT(ic));
13409       offset = 0;
13410       while (size--) {
13411         pic16_emitcode ("pop","acc");
13412         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13413       }
13414   } else {
13415     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13416     _G.accInUse++;
13417     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13418     _G.accInUse--;
13419
13420     /* set pseudo stack pointer to where it should be - dw*/
13421     GpsuedoStkPtr = ic->parmBytes;
13422
13423     /* setting GpsuedoStkPtr has side effects here: */
13424     assignResultValue(IC_RESULT(ic), 0);
13425   }
13426
13427   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13428 }
13429
13430 /*-----------------------------------------------------------------*/
13431 /* genDummyRead - generate code for dummy read of volatiles        */
13432 /*-----------------------------------------------------------------*/
13433 static void
13434 genDummyRead (iCode * ic)
13435 {
13436   pic16_emitcode ("; genDummyRead","");
13437   pic16_emitcode ("; not implemented","");
13438
13439   ic = ic;
13440 }
13441
13442 /*-----------------------------------------------------------------*/
13443 /* genpic16Code - generate code for pic16 based controllers        */
13444 /*-----------------------------------------------------------------*/
13445 /*
13446  * At this point, ralloc.c has gone through the iCode and attempted
13447  * to optimize in a way suitable for a PIC. Now we've got to generate
13448  * PIC instructions that correspond to the iCode.
13449  *
13450  * Once the instructions are generated, we'll pass through both the
13451  * peep hole optimizer and the pCode optimizer.
13452  *-----------------------------------------------------------------*/
13453
13454 void genpic16Code (iCode *lic)
13455 {
13456   iCode *ic;
13457   int cln = 0;
13458
13459     lineHead = lineCurr = NULL;
13460
13461     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13462     pic16_addpBlock(pb);
13463
13464 #if 0
13465     /* if debug information required */
13466     if (options.debug && currFunc) {
13467       if (currFunc) {
13468         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13469       }
13470     }
13471 #endif
13472
13473     for (ic = lic ; ic ; ic = ic->next ) {
13474
13475       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
13476       if ( cln != ic->lineno ) {
13477         if ( options.debug ) {
13478           debugFile->writeCLine (ic);
13479         }
13480         
13481         if(!options.noCcodeInAsm) {
13482           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13483               printCLine(ic->filename, ic->lineno)));
13484         }
13485
13486         cln = ic->lineno ;
13487       }
13488         
13489       if(options.iCodeInAsm) {
13490         char *l;
13491
13492           /* insert here code to print iCode as comment */
13493           l = Safe_strdup(printILine(ic));
13494           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13495       }
13496         
13497       /* if the result is marked as
13498        * spilt and rematerializable or code for
13499        * this has already been generated then
13500        * do nothing */
13501       if (resultRemat(ic) || ic->generated ) 
13502         continue ;
13503         
13504       /* depending on the operation */
13505       switch (ic->op) {
13506         case '!' :
13507           pic16_genNot(ic);
13508           break;
13509             
13510         case '~' :
13511           pic16_genCpl(ic);
13512           break;
13513             
13514         case UNARYMINUS:
13515           genUminus (ic);
13516           break;
13517             
13518         case IPUSH:
13519           genIpush (ic);
13520           break;
13521             
13522         case IPOP:
13523           /* IPOP happens only when trying to restore a 
13524            * spilt live range, if there is an ifx statement
13525            * following this pop then the if statement might
13526            * be using some of the registers being popped which
13527            * would destroy the contents of the register so
13528            * we need to check for this condition and handle it */
13529            if (ic->next
13530              && ic->next->op == IFX
13531              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13532                genIfx (ic->next,ic);
13533           else
13534             genIpop (ic);
13535           break; 
13536             
13537         case CALL:
13538           genCall (ic);
13539           break;
13540             
13541         case PCALL:
13542           genPcall (ic);
13543           break;
13544             
13545         case FUNCTION:
13546           genFunction (ic);
13547           break;
13548             
13549         case ENDFUNCTION:
13550           genEndFunction (ic);
13551           break;
13552             
13553         case RETURN:
13554           genRet (ic);
13555           break;
13556             
13557         case LABEL:
13558           genLabel (ic);
13559           break;
13560             
13561         case GOTO:
13562           genGoto (ic);
13563           break;
13564             
13565         case '+' :
13566           pic16_genPlus (ic) ;
13567           break;
13568             
13569         case '-' :
13570           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13571             pic16_genMinus (ic);
13572           break;
13573
13574         case '*' :
13575           genMult (ic);
13576           break;
13577             
13578         case '/' :
13579           genDiv (ic) ;
13580           break;
13581             
13582         case '%' :
13583           genMod (ic);
13584           break;
13585             
13586         case '>' :
13587           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13588           break;
13589             
13590         case '<' :
13591           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13592           break;
13593             
13594         case LE_OP:
13595         case GE_OP:
13596         case NE_OP:
13597           /* note these two are xlated by algebraic equivalence
13598            * during parsing SDCC.y */
13599           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13600             "got '>=' or '<=' shouldn't have come here");
13601           break;
13602
13603         case EQ_OP:
13604           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13605           break;            
13606             
13607         case AND_OP:
13608           genAndOp (ic);
13609           break;
13610             
13611         case OR_OP:
13612           genOrOp (ic);
13613           break;
13614             
13615         case '^' :
13616           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13617           break;
13618             
13619         case '|' :
13620           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13621           break;
13622             
13623         case BITWISEAND:
13624           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13625           break;
13626             
13627         case INLINEASM:
13628           genInline (ic);
13629           break;
13630             
13631         case RRC:
13632           genRRC (ic);
13633           break;
13634             
13635         case RLC:
13636           genRLC (ic);
13637           break;
13638             
13639         case GETHBIT:
13640           genGetHbit (ic);
13641           break;
13642             
13643         case LEFT_OP:
13644           genLeftShift (ic);
13645           break;
13646             
13647         case RIGHT_OP:
13648           genRightShift (ic);
13649           break;
13650             
13651         case GET_VALUE_AT_ADDRESS:
13652           genPointerGet(ic);
13653           break;
13654             
13655         case '=' :
13656           if (POINTER_SET(ic))
13657             genPointerSet(ic);
13658           else
13659             genAssign(ic);
13660           break;
13661             
13662         case IFX:
13663           genIfx (ic,NULL);
13664           break;
13665             
13666         case ADDRESS_OF:
13667           genAddrOf (ic);
13668           break;
13669             
13670         case JUMPTABLE:
13671           genJumpTab (ic);
13672           break;
13673             
13674         case CAST:
13675           genCast (ic);
13676           break;
13677             
13678         case RECEIVE:
13679           genReceive(ic);
13680           break;
13681             
13682         case SEND:
13683           addSet(&_G.sendSet,ic);
13684           break;
13685
13686         case DUMMY_READ_VOLATILE:
13687           genDummyRead (ic);
13688           break;
13689
13690         default :
13691           ic = ic;
13692       }
13693     }
13694
13695
13696     /* now we are ready to call the
13697        peep hole optimizer */
13698     if (!options.nopeep)
13699       peepHole (&lineHead);
13700
13701     /* now do the actual printing */
13702     printLine (lineHead, codeOutFile);
13703
13704 #ifdef PCODE_DEBUG
13705     DFPRINTF((stderr,"printing pBlock\n\n"));
13706     pic16_printpBlock(stdout,pb);
13707 #endif
13708
13709     return;
13710 }
13711