c0ba6354cb0ad9b23d73e305e4b64e1137def97d
[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 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4752 #define DEBUGpc(fmt,...)  DEBUGpic16_emitcode("; =:=", "%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
4753 #endif
4754 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
4755 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE || AOP_TYPE(x) == AOP_STA)
4756
4757 /*-----------------------------------------------------------------*/
4758 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4759 /*                  aop (if it's NOT a literal) or from lit (if    */
4760 /*                  aop is a literal)                              */
4761 /*-----------------------------------------------------------------*/
4762 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4763   if (aop->type == AOP_LIT) {
4764     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4765   } else {
4766     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4767   }
4768 }
4769
4770 /*-----------------------------------------------------------------*/
4771 /* genCmp :- greater or less than comparison                       */
4772 /*-----------------------------------------------------------------*/
4773
4774 #if USE_SIMPLE_GENCMP
4775
4776 /* genCmp performs a left < right comparison, stores
4777  * the outcome in result (if != NULL) and generates
4778  * control flow code for the ifx (if != NULL).
4779  *
4780  * This version leaves in sequences like
4781  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4782  * which should be optmized by the peephole
4783  * optimizer - RN 2005-01-01 */
4784 static void genCmp (operand *left,operand *right,
4785                     operand *result, iCode *ifx, int sign)
4786 {
4787   resolvedIfx rIfx;
4788   int size;
4789   int offs;
4790   symbol *templbl;
4791   operand *dummy;
4792   unsigned long lit;
4793   unsigned long mask;
4794   int performedLt;
4795
4796   FENTRY;
4797   
4798   assert (AOP_SIZE(left) == AOP_SIZE(right));
4799   assert (left && right);
4800
4801   size = AOP_SIZE(right) - 1;
4802   mask = (0x100UL << (size*8)) - 1;
4803   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4804   performedLt = 1;
4805   templbl = NULL;
4806   lit = 0;
4807   
4808   resolveIfx (&rIfx, ifx);
4809
4810   /**********************************************************************
4811    * handle bits - bit compares are promoted to int compares seemingly! *
4812    **********************************************************************/
4813 #if 0
4814   // THIS IS COMPLETELY UNTESTED!
4815   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4816     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4817     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4818     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4819
4820     emitSETC;
4821     // 1 < {0,1} is false --> clear C by skipping the next instruction
4822     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4823     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4824     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4825     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4826     emitCLRC; // only skipped for left=0 && right=1
4827
4828     goto correct_result_in_carry;
4829   } // if
4830 #endif
4831
4832   /*************************************************
4833    * make sure that left is register (or the like) *
4834    *************************************************/
4835   if (!isAOP_REGlike(left)) {
4836     #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4837     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4838     #endif
4839     assert (isAOP_LIT(left));
4840     assert (isAOP_REGlike(right));
4841     // swap left and right
4842     // left < right <==> right > left <==> (right >= left + 1)
4843     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4844
4845     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4846       // MAXVALUE < right? always false
4847       if (performedLt) emitCLRC; else emitSETC;
4848       goto correct_result_in_carry;
4849     } // if
4850
4851     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4852     // that's we handled it above.
4853     lit++;
4854
4855     dummy = left;
4856     left = right;
4857     right = dummy;
4858
4859     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
4860   } else if (isAOP_LIT(right)) {
4861     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4862   } // if
4863
4864   assert (isAOP_REGlike(left)); // left must be register or the like
4865   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4866
4867   /*************************************************
4868    * special cases go here                         *
4869    *************************************************/
4870
4871   if (isAOP_LIT(right)) {
4872     if (!sign) {
4873       // unsigned comparison to a literal
4874       #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4875       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4876       #endif
4877       if (lit == 0) {
4878         // unsigned left < 0? always false
4879         if (performedLt) emitCLRC; else emitSETC;
4880         goto correct_result_in_carry;
4881       }
4882     } else {
4883       // signed comparison to a literal
4884       #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4885       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4886       #endif
4887       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4888         // signed left < 0x80000000? always false
4889         if (performedLt) emitCLRC; else emitSETC;
4890         goto correct_result_in_carry;
4891       } else if (lit == 0) {
4892         // compare left < 0; set CARRY if SIGNBIT(left) is set
4893         if (performedLt) emitSETC; else emitCLRC;
4894         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4895         if (performedLt) emitCLRC; else emitSETC;
4896         goto correct_result_in_carry;
4897       }
4898     } // if (!sign)
4899   } // right is literal
4900
4901   /*************************************************
4902    * perform a general case comparison             *
4903    * make sure we get CARRY==1 <==> left >= right  *
4904    *************************************************/
4905   // compare most significant bytes
4906   //DEBUGpc ("comparing bytes at offset %d", size);
4907   if (!sign) {
4908     // unsigned comparison
4909     mov2w_regOrLit (AOP(right), lit, size);
4910     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
4911   } else {
4912     // signed comparison
4913     // (add 2^n to both operands then perform an unsigned comparison)
4914     if (isAOP_LIT(right)) {
4915       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4916       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4917
4918       if (litbyte == 0x80) {
4919         // left >= 0x80 -- always true, but more bytes to come
4920         pic16_mov2w (AOP(left), size);
4921         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
4922         emitSETC;
4923       } else {
4924         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4925         pic16_mov2w (AOP(left), size);
4926         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4927         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4928       } // if
4929     } else {
4930       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
4931       //pCodeOp *pctemp = pic16_popGetTempReg(1);
4932       pic16_mov2w (AOP(left), size);
4933       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4934       pic16_emitpcode (POC_MOVWF, pctemp);
4935       pic16_mov2w (AOP(right), size);
4936       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4937       pic16_emitpcode (POC_SUBFW, pctemp);
4938       //pic16_popReleaseTempReg(pctemp, 1);
4939     }
4940   } // if (!sign)
4941
4942   // compare remaining bytes (treat as unsigned case from above)
4943   templbl = newiTempLabel ( NULL );
4944   offs = size;
4945   while (offs--) {
4946     //DEBUGpc ("comparing bytes at offset %d", offs);
4947     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
4948     mov2w_regOrLit (AOP(right), lit, offs);
4949     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
4950   } // while (offs)
4951   pic16_emitpLabel (templbl->key);
4952   goto result_in_carry;
4953
4954 result_in_carry:
4955   
4956   /****************************************************
4957    * now CARRY contains the result of the comparison: *
4958    * SUBWF sets CARRY iff                             *
4959    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4960    * (F=left, W=right)
4961    ****************************************************/
4962
4963   if (performedLt) {
4964     if (result && AOP_TYPE(result) != AOP_CRY) {
4965       // value will be stored
4966       emitTOGC;
4967     } else {
4968       // value wil only be used in the following genSkipc()
4969       rIfx.condition ^= 1;
4970     }
4971   } // if
4972
4973 correct_result_in_carry:
4974
4975   // assign result to variable (if neccessary)
4976   if (result && AOP_TYPE(result) != AOP_CRY) {
4977     //DEBUGpc ("assign result");
4978     size = AOP_SIZE(result);
4979     while (size--) {
4980       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
4981     } // while
4982     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
4983   } // if (result)
4984
4985   // perform conditional jump
4986   // genSkipc branches to rifx->label if (rifx->condition != CARRY)
4987   if (ifx) {
4988     //DEBUGpc ("generate control flow");
4989     rIfx.condition ^= 1;
4990     genSkipc (&rIfx);
4991     ifx->generated = 1;
4992   } // if
4993 }
4994
4995 #elif 1
4996                 /* { */
4997       /* original code */
4998 static void genCmp (operand *left,operand *right,
4999                     operand *result, iCode *ifx, int sign)
5000 {
5001   int size; //, offset = 0 ;
5002   unsigned long lit = 0L,i = 0;
5003   resolvedIfx rFalseIfx;
5004   //  resolvedIfx rTrueIfx;
5005   symbol *truelbl;
5006   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5007 /*
5008   if(ifx) {
5009     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5010     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5011   }
5012 */
5013
5014   FENTRY;
5015   
5016   resolveIfx(&rFalseIfx,ifx);
5017   truelbl  = newiTempLabel(NULL);
5018   size = max(AOP_SIZE(left),AOP_SIZE(right));
5019
5020   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5021
5022 #define _swapp
5023
5024   /* if literal is on the right then swap with left */
5025   if ((AOP_TYPE(right) == AOP_LIT)) {
5026     operand *tmp = right ;
5027     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5028     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5029 #ifdef _swapp
5030
5031     lit = (lit - 1) & mask;
5032     right = left;
5033     left = tmp;
5034     rFalseIfx.condition ^= 1;
5035 #endif
5036
5037   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5038     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5039   }
5040
5041
5042   //if(IC_TRUE(ifx) == NULL)
5043   /* if left & right are bit variables */
5044   if (AOP_TYPE(left) == AOP_CRY &&
5045       AOP_TYPE(right) == AOP_CRY ) {
5046     assert (0 && "bit variables used in genCmp");
5047     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5048     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5049   } else {
5050     /* subtract right from left if at the
5051        end the carry flag is set then we know that
5052        left is greater than right */
5053
5054     symbol *lbl  = newiTempLabel(NULL);
5055
5056 #if 0
5057         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5058                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5059 #endif
5060
5061 #ifndef _swapp
5062     if(AOP_TYPE(right) == AOP_LIT) {
5063
5064       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5065
5066       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5067
5068       /* special cases */
5069
5070       if(lit == 0) {
5071
5072         if(sign != 0) 
5073           genSkipCond(&rFalseIfx,left,size-1,7);
5074         else 
5075           /* no need to compare to 0...*/
5076           /* NOTE: this is a de-generate compare that most certainly 
5077            *       creates some dead code. */
5078           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5079
5080         if(ifx) ifx->generated = 1;
5081         return;
5082
5083       }
5084       size--;
5085
5086       if(size == 0) {
5087         //i = (lit >> (size*8)) & 0xff;
5088         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5089         
5090         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5091
5092         i = ((0-lit) & 0xff);
5093         if(sign) {
5094           if( i == 0x81) { 
5095             /* lit is 0x7f, all signed chars are less than
5096              * this except for 0x7f itself */
5097             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5098             genSkipz2(&rFalseIfx,0);
5099           } else {
5100             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5101             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5102             genSkipc(&rFalseIfx);
5103           }
5104
5105         } else {
5106           if(lit == 1) {
5107             genSkipz2(&rFalseIfx,1);
5108           } else {
5109             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5110             genSkipc(&rFalseIfx);
5111           }
5112         }
5113
5114         if(ifx) ifx->generated = 1;
5115         return;
5116       }
5117
5118       /* chars are out of the way. now do ints and longs */
5119
5120
5121       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5122         
5123       /* special cases */
5124
5125       if(sign) {
5126
5127         if(lit == 0) {
5128           genSkipCond(&rFalseIfx,left,size,7);
5129           if(ifx) ifx->generated = 1;
5130           return;
5131         }
5132
5133         if(lit <0x100) {
5134           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5135
5136           //rFalseIfx.condition ^= 1;
5137           //genSkipCond(&rFalseIfx,left,size,7);
5138           //rFalseIfx.condition ^= 1;
5139
5140           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5141           if(rFalseIfx.condition)
5142             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5143           else
5144             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5145
5146           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5147           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5148           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5149
5150           while(size > 1)
5151             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5152
5153           if(rFalseIfx.condition) {
5154             emitSKPZ;
5155             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5156
5157           } else {
5158             emitSKPNZ;
5159           }
5160
5161           genSkipc(&rFalseIfx);
5162           pic16_emitpLabel(truelbl->key);
5163           if(ifx) ifx->generated = 1;
5164           return;
5165
5166         }
5167
5168         if(size == 1) {
5169
5170           if( (lit & 0xff) == 0) {
5171             /* lower byte is zero */
5172             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5173             i = ((lit >> 8) & 0xff) ^0x80;
5174             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5175             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5176             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5177             genSkipc(&rFalseIfx);
5178
5179
5180             if(ifx) ifx->generated = 1;
5181             return;
5182
5183           }
5184         } else {
5185           /* Special cases for signed longs */
5186           if( (lit & 0xffffff) == 0) {
5187             /* lower byte is zero */
5188             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5189             i = ((lit >> 8*3) & 0xff) ^0x80;
5190             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5191             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5192             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5193             genSkipc(&rFalseIfx);
5194
5195
5196             if(ifx) ifx->generated = 1;
5197             return;
5198
5199           }
5200
5201         }
5202
5203
5204         if(lit & (0x80 << (size*8))) {
5205           /* lit is negative */
5206           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5207
5208           //genSkipCond(&rFalseIfx,left,size,7);
5209
5210           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5211
5212           if(rFalseIfx.condition)
5213             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5214           else
5215             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5216
5217
5218         } else {
5219           /* lit is positive */
5220           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5221           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5222           if(rFalseIfx.condition)
5223             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5224           else
5225             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5226
5227         }
5228
5229         /*
5230           This works, but is only good for ints.
5231           It also requires a "known zero" register.
5232           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5233           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5234           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5235           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5236           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5237           genSkipc(&rFalseIfx);
5238
5239           pic16_emitpLabel(truelbl->key);
5240           if(ifx) ifx->generated = 1;
5241           return;
5242         **/
5243           
5244         /* There are no more special cases, so perform a general compare */
5245   
5246         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5247         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5248
5249         while(size--) {
5250
5251           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5252           emitSKPNZ;
5253           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5254         }
5255         //rFalseIfx.condition ^= 1;
5256         genSkipc(&rFalseIfx);
5257
5258         pic16_emitpLabel(truelbl->key);
5259
5260         if(ifx) ifx->generated = 1;
5261         return;
5262
5263
5264       }
5265
5266
5267       /* sign is out of the way. So now do an unsigned compare */
5268       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5269
5270
5271       /* General case - compare to an unsigned literal on the right.*/
5272
5273       i = (lit >> (size*8)) & 0xff;
5274       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5275       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5276       while(size--) {
5277         i = (lit >> (size*8)) & 0xff;
5278
5279         if(i) {
5280           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5281           emitSKPNZ;
5282           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5283         } else {
5284           /* this byte of the lit is zero, 
5285            *if it's not the last then OR in the variable */
5286           if(size)
5287             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5288         }
5289       }
5290
5291
5292       pic16_emitpLabel(lbl->key);
5293 //      pic16_emitpLabel(truelbl->key);
5294       //if(emitFinalCheck)
5295       genSkipc(&rFalseIfx);
5296       if(sign)
5297         pic16_emitpLabel(truelbl->key);
5298
5299       if(ifx) ifx->generated = 1;
5300       return;
5301
5302
5303     }
5304 #endif  // _swapp
5305
5306     if(AOP_TYPE(left) == AOP_LIT) {
5307       //symbol *lbl = newiTempLabel(NULL);
5308
5309       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5310
5311
5312       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5313
5314       /* Special cases */
5315       if((lit == 0) && (sign == 0)){
5316
5317         size--;
5318         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5319         while(size) 
5320           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5321
5322         genSkipz2(&rFalseIfx,0);
5323         if(ifx) ifx->generated = 1;
5324         return;
5325       }
5326
5327       if(size==1) {
5328         /* Special cases */
5329         lit &= 0xff;
5330         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5331           /* degenerate compare can never be true */
5332           if(rFalseIfx.condition == 0)
5333             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5334
5335           if(ifx) ifx->generated = 1;
5336           return;
5337         }
5338
5339         if(sign) {
5340           /* signed comparisons to a literal byte */
5341
5342           int lp1 = (lit+1) & 0xff;
5343
5344           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5345           switch (lp1) {
5346           case 0:
5347             rFalseIfx.condition ^= 1;
5348             genSkipCond(&rFalseIfx,right,0,7);
5349             break;
5350           case 0x7f:
5351             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5352             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5353             genSkipz2(&rFalseIfx,1);
5354             break;
5355           default:
5356             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5357             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5358             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5359             rFalseIfx.condition ^= 1;
5360             genSkipc(&rFalseIfx);
5361             break;
5362           }
5363         } else {
5364           /* unsigned comparisons to a literal byte */
5365
5366           switch(lit & 0xff ) {
5367           case 0:
5368             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5369             genSkipz2(&rFalseIfx,0);
5370             break;
5371           case 0x7f:
5372             rFalseIfx.condition ^= 1;
5373             genSkipCond(&rFalseIfx,right,0,7);
5374             break;
5375
5376           default:
5377             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5378             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5379             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5380             rFalseIfx.condition ^= 1;
5381             if (AOP_TYPE(result) == AOP_CRY)
5382               genSkipc(&rFalseIfx);
5383             else {
5384               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5385               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5386             }         
5387             break;
5388           }
5389         }
5390
5391         if(ifx) ifx->generated = 1;
5392         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5393                 goto check_carry;
5394         return;
5395
5396       } else {
5397
5398         /* Size is greater than 1 */
5399
5400         if(sign) {
5401           int lp1 = lit+1;
5402
5403           size--;
5404
5405           if(lp1 == 0) {
5406             /* this means lit = 0xffffffff, or -1 */
5407
5408
5409             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5410             rFalseIfx.condition ^= 1;
5411             genSkipCond(&rFalseIfx,right,size,7);
5412             if(ifx) ifx->generated = 1;
5413
5414             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5415               goto check_carry;
5416
5417             return;
5418           }
5419
5420           if(lit == 0) {
5421             int s = size;
5422
5423             if(rFalseIfx.condition) {
5424               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5425               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5426             }
5427
5428             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5429             while(size--)
5430               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5431
5432
5433             emitSKPZ;
5434             if(rFalseIfx.condition) {
5435               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5436               pic16_emitpLabel(truelbl->key);
5437             }else {
5438               rFalseIfx.condition ^= 1;
5439               genSkipCond(&rFalseIfx,right,s,7);
5440             }
5441
5442             if(ifx) ifx->generated = 1;
5443
5444             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5445               goto check_carry;
5446
5447             return;
5448           }
5449
5450           if((size == 1) &&  (0 == (lp1&0xff))) {
5451             /* lower byte of signed word is zero */
5452             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5453             i = ((lp1 >> 8) & 0xff) ^0x80;
5454             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5455             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5456             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5457
5458             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5459               emitTOGC;
5460               if(ifx) ifx->generated = 1;
5461               goto check_carry;
5462             } else {
5463               rFalseIfx.condition ^= 1;
5464               genSkipc(&rFalseIfx);
5465               if(ifx) ifx->generated = 1;
5466             }
5467
5468             return;
5469           }
5470
5471           if(lit & (0x80 << (size*8))) {
5472             /* Lit is less than zero */
5473             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5474             //rFalseIfx.condition ^= 1;
5475             //genSkipCond(&rFalseIfx,left,size,7);
5476             //rFalseIfx.condition ^= 1;
5477             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5478             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5479
5480             if(rFalseIfx.condition)
5481               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5482             else
5483               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5484
5485
5486           } else {
5487             /* Lit is greater than or equal to zero */
5488             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5489             //rFalseIfx.condition ^= 1;
5490             //genSkipCond(&rFalseIfx,right,size,7);
5491             //rFalseIfx.condition ^= 1;
5492
5493             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5494             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5495
5496             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5497             if(rFalseIfx.condition)
5498               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5499             else
5500               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5501
5502           }
5503
5504           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5505           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5506
5507           while(size--) {
5508
5509             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5510             emitSKPNZ;
5511             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5512           }
5513           rFalseIfx.condition ^= 1;
5514           //rFalseIfx.condition = 1;
5515           genSkipc(&rFalseIfx);
5516
5517           pic16_emitpLabel(truelbl->key);
5518
5519           if(ifx) ifx->generated = 1;
5520
5521
5522           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5523             goto check_carry;
5524
5525           return;
5526           // end of if (sign)
5527         } else {
5528
5529           /* compare word or long to an unsigned literal on the right.*/
5530
5531
5532           size--;
5533           if(lit < 0xff) {
5534             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5535             switch (lit) {
5536             case 0:
5537               break; /* handled above */
5538 /*
5539             case 0xff:
5540               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5541               while(size--)
5542                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5543               genSkipz2(&rFalseIfx,0);
5544               break;
5545 */
5546             default:
5547               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5548               while(--size)
5549                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5550
5551               emitSKPZ;
5552               if(rFalseIfx.condition)
5553                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5554               else
5555                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5556
5557
5558               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5559               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5560
5561               rFalseIfx.condition ^= 1;
5562               genSkipc(&rFalseIfx);
5563             }
5564
5565             pic16_emitpLabel(truelbl->key);
5566
5567             if(ifx) ifx->generated = 1;
5568
5569             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5570               goto check_carry;
5571
5572             return;
5573           }
5574
5575
5576           lit++;
5577           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5578           i = (lit >> (size*8)) & 0xff;
5579
5580           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5581           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5582
5583           while(size--) {
5584             i = (lit >> (size*8)) & 0xff;
5585
5586             if(i) {
5587               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5588               emitSKPNZ;
5589               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5590             } else {
5591               /* this byte of the lit is zero, 
5592                * if it's not the last then OR in the variable */
5593               if(size)
5594                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5595             }
5596           }
5597
5598
5599           pic16_emitpLabel(lbl->key);
5600
5601           rFalseIfx.condition ^= 1;
5602
5603           genSkipc(&rFalseIfx);
5604         }
5605
5606         if(sign)
5607           pic16_emitpLabel(truelbl->key);
5608         if(ifx) ifx->generated = 1;
5609
5610             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5611               goto check_carry;
5612
5613         return;
5614       }
5615     }
5616     /* Compare two variables */
5617
5618     DEBUGpic16_emitcode(";sign","%d",sign);
5619
5620     size--;
5621     if(sign) {
5622       /* Sigh. thus sucks... */
5623       if(size) {
5624         pCodeOp *pctemp;
5625         
5626         pctemp = pic16_popGetTempReg(1);
5627         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5628         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5629         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5630         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5631         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5632         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5633         pic16_popReleaseTempReg(pctemp, 1);
5634       } else {
5635         /* Signed char comparison */
5636         /* Special thanks to Nikolai Golovchenko for this snippet */
5637         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5638         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5639         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5640         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5641         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5642         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5643
5644         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5645         genSkipc(&rFalseIfx);
5646           
5647         if(ifx) ifx->generated = 1;
5648
5649             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5650               goto check_carry;
5651
5652         return;
5653       }
5654
5655     } else {
5656
5657       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5658       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5659     }
5660
5661
5662     /* The rest of the bytes of a multi-byte compare */
5663     while (size) {
5664
5665       emitSKPZ;
5666       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5667       size--;
5668
5669       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5670       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5671
5672
5673     }
5674
5675     pic16_emitpLabel(lbl->key);
5676
5677     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5678     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5679         (AOP_TYPE(result) == AOP_REG)) {
5680       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5681       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5682     } else {
5683       genSkipc(&rFalseIfx);
5684     }         
5685     //genSkipc(&rFalseIfx);
5686     if(ifx) ifx->generated = 1;
5687
5688
5689             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5690               goto check_carry;
5691
5692     return;
5693
5694   }
5695
5696 check_carry:
5697   if ((AOP_TYPE(result) != AOP_CRY) 
5698         && AOP_SIZE(result)) {
5699     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5700
5701     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5702
5703     pic16_outBitC(result);
5704   } else {
5705     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5706     /* if the result is used in the next
5707        ifx conditional branch then generate
5708        code a little differently */
5709     if (ifx )
5710       genIfxJump (ifx,"c");
5711     else
5712       pic16_outBitC(result);
5713     /* leave the result in acc */
5714   }
5715
5716 }
5717
5718 #else   /* old version of genCmp() */   /* } else { */
5719
5720 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5721 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5722         operand *result, int offset, int invert_op)
5723 {
5724   /* add code here */
5725   
5726   /* check condition, > or < ?? */
5727   if(rIfx->condition != 0)invert_op ^= 1;
5728   
5729   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5730
5731   if(!ifx)invert_op ^= 1;
5732
5733   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5734       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5735   
5736   /* do selection */
5737   if(!invert_op)return POC_CPFSGT;
5738   else return POC_CPFSLT;
5739 }
5740
5741 static int compareAopfirstpass=1;
5742
5743 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5744             operand *oper, int offset, operand *result,
5745             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5746             symbol *tlbl)
5747 {
5748   int op;
5749   symbol *truelbl;
5750
5751   /* invert if there is a result to be loaded, in order to fit,
5752    * SETC/CLRC sequence */
5753   if(AOP_SIZE(result))invert_op ^= 1;
5754
5755 //  if(sign && !offset)invert_op ^= 1;
5756   
5757 //  if(sign)invert_op ^= 1;
5758   
5759   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5760
5761   if(AOP_SIZE(result) && compareAopfirstpass) {
5762     if(!ifx) {
5763       if(pcop2)
5764         pic16_emitpcode(POC_SETF, pcop2);
5765       else
5766         emitSETC;
5767     } else {
5768       if(pcop2)
5769         pic16_emitpcode(POC_CLRF, pcop2);
5770       else
5771         emitCLRC;
5772     }
5773   }
5774
5775   compareAopfirstpass = 0;
5776
5777       /* there is a bug when comparing operands with size > 1,
5778        * because higher bytes can be equal and test should be performed
5779        * to the next lower byte, current algorithm, considers operands
5780        * inequal in these cases! -- VR 20041107 */
5781
5782     
5783   if(pcop)
5784     pic16_emitpcode(op, pcop);
5785   else
5786     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5787
5788
5789   if((!sign || !offset) && AOP_SIZE(result)) {
5790     if(!ifx) {
5791       if(pcop2)
5792         pic16_emitpcode(POC_CLRF, pcop2);
5793         else
5794         emitCLRC;
5795     } else {
5796       if(pcop2)
5797         pic16_emitpcode(POC_SETF, pcop2);
5798       else
5799         emitSETC;
5800     }
5801     
5802     /* don't emit final branch (offset == 0) */
5803     if(offset) {
5804
5805       if(pcop2)
5806         pic16_emitpcode(POC_RRCF, pcop2);
5807
5808       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5809     }
5810   } else {
5811     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5812       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5813             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5814
5815       truelbl = newiTempLabel( NULL );
5816       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5817       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5818         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5819       else
5820         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5821       pic16_emitpLabel(truelbl->key);
5822     } else {
5823       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5824     }
5825   }
5826 }
5827
5828
5829   
5830
5831 #if 1   /* { */
5832 static void genCmp (operand *left, operand *right,
5833                     operand *result, iCode *ifx, int sign)
5834 {
5835   int size, cmpop=1;
5836   long lit = 0L;
5837   resolvedIfx rFalseIfx;
5838   symbol *falselbl, *tlbl;
5839
5840     FENTRY;
5841     
5842     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5843
5844     resolveIfx(&rFalseIfx, ifx);
5845     size = max(AOP_SIZE(left), AOP_SIZE(right));
5846     
5847     /* if left & right are bit variables */
5848     if(AOP_TYPE(left) == AOP_CRY
5849       && AOP_TYPE(right) == AOP_CRY ) {
5850
5851         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5852         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5853         
5854         werror(W_POSSBUG2, __FILE__, __LINE__);
5855         exit(-1);
5856     }
5857     
5858     /* if literal is on the right then swap with left */
5859     if((AOP_TYPE(right) == AOP_LIT)) {
5860       operand *tmp = right ;
5861 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
5862
5863         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5864
5865 //      lit = (lit - 1) & mask;
5866         right = left;
5867         left = tmp;
5868         rFalseIfx.condition ^= 1;               /* reverse compare */
5869     } else
5870     if ((AOP_TYPE(left) == AOP_LIT)) {
5871       /* float compares are handled by support functions */
5872       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5873     }
5874
5875     /* actual comparing algorithm */
5876 //    size = AOP_SIZE( right );
5877
5878     falselbl = newiTempLabel( NULL );
5879     if(AOP_TYPE(left) == AOP_LIT) {
5880       /* compare to literal */
5881       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5882       
5883       if(sign) {
5884         pCodeOp *pct, *pct2;
5885         symbol *tlbl1;
5886
5887         /* signed compare */
5888         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5889
5890         pct = pic16_popCopyReg(&pic16_pc_prodl);
5891         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5892         tlbl = newiTempLabel( NULL );
5893         
5894         /* first compare signs:
5895          *  a. if both are positive, compare just like unsigned
5896          *  b. if both are negative, invert cmpop, compare just like unsigned
5897          *  c. if different signs, determine the result directly */
5898
5899         size--;
5900
5901 #if 1
5902         /* { */
5903         tlbl1 = newiTempLabel( NULL );
5904 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
5905
5906         if(lit > 0) {
5907
5908           /* literal is zero or positive:
5909            *  a. if carry is zero, too, continue compare,
5910            *  b. if carry is set, then continue depending on cmpop ^ condition:
5911            *    1. '<' return false (literal < variable),
5912            *    2. '>' return true (literal > variable) */
5913 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
5914           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5915           
5916           
5917           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5918           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
5919         } else 
5920         if(lit < 0) {
5921           
5922           /* literal is negative:
5923            *  a. if carry is set, too, continue compare,
5924            *  b. if carry is zero, then continue depending on cmpop ^ condition:
5925            *    1. '<' return true (literal < variable),
5926            *    2. '>' return false (literal > variable) */
5927 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
5928           pic16_emitpcode(POC_BTFSS, 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 #if 1
5934         else {
5935           /* lit == 0 */
5936           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5937           
5938           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5939           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5940         }
5941 #endif
5942         
5943         
5944         pic16_emitpLabel( tlbl1->key );
5945 #endif  /* } */
5946
5947         compareAopfirstpass=1;
5948 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5949 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5950 //        pic16_emitpcode(POC_MOVWF, pct);
5951
5952 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5953         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5954 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5955         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5956
5957         /* generic case */        
5958           while( size-- ) {
5959 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5960 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
5961 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5962 //            pic16_emitpcode(POC_MOVWF, pct);
5963
5964 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5965             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
5966             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5967 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5968 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
5969           }
5970 //        }
5971         
5972         if(ifx)ifx->generated = 1;
5973
5974         if(AOP_SIZE(result)) {
5975           pic16_emitpLabel(tlbl->key);
5976           pic16_emitpLabel(falselbl->key);
5977           pic16_outBitOp( result, pct2 );
5978         } else {
5979           pic16_emitpLabel(tlbl->key);
5980         }
5981       } else {
5982
5983
5984         /* unsigned compare */      
5985         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
5986     
5987         compareAopfirstpass=1;
5988         while(size--) {
5989           
5990           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5991           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
5992
5993         }
5994
5995         if(ifx)ifx->generated = 1;
5996
5997
5998         if(AOP_SIZE(result)) {
5999           pic16_emitpLabel(falselbl->key);
6000           pic16_outBitC( result );
6001         }
6002
6003       }
6004     } else {
6005       /* compare registers */
6006       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6007
6008
6009       if(sign) {
6010         pCodeOp *pct, *pct2;
6011         
6012         /* signed compare */
6013         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6014
6015         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6016         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6017         tlbl = newiTempLabel( NULL );
6018         
6019         compareAopfirstpass=1;
6020
6021         size--;
6022         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6023 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6024         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6025         pic16_emitpcode(POC_MOVWF, pct);
6026
6027         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6028 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6029         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6030
6031         /* WREG already holds left + 0x80 */
6032         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6033         
6034         while( size-- ) {
6035           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6036 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6037           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6038           pic16_emitpcode(POC_MOVWF, pct);
6039                 
6040           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6041 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6042           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6043
6044           /* WREG already holds left + 0x80 */
6045           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6046 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6047         }
6048         
6049         if(ifx)ifx->generated = 1;
6050
6051         if(AOP_SIZE(result)) {
6052           pic16_emitpLabel(tlbl->key);
6053           pic16_emitpLabel(falselbl->key);
6054           pic16_outBitOp( result, pct2 );
6055         } else {
6056           pic16_emitpLabel(tlbl->key);
6057         }
6058
6059       } else {
6060         /* unsigned compare */      
6061         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6062
6063         compareAopfirstpass=1;
6064         while(size--) {
6065           
6066           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6067           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6068
6069         }
6070
6071         if(ifx)ifx->generated = 1;
6072         if(AOP_SIZE(result)) {
6073
6074           pic16_emitpLabel(falselbl->key);
6075           pic16_outBitC( result );
6076         }
6077
6078       }
6079     }
6080 }
6081
6082 #else    /* } else { */
6083
6084 /* new version of genCmp -- VR 20041012 */
6085 static void genCmp (operand *left,operand *right,
6086                     operand *result, iCode *ifx, int sign)
6087 {
6088   int size; //, offset = 0 ;
6089   unsigned long lit = 0L,i = 0;
6090   resolvedIfx rFalseIfx;
6091   int willCheckCarry=0;
6092   //  resolvedIfx rTrueIfx;
6093   symbol *truelbl;
6094
6095     FENTRY;
6096   
6097   /* General concept:
6098    * subtract right from left if at the end the carry flag is set then we
6099    * know that left is greater than right */
6100             
6101   resolveIfx(&rFalseIfx,ifx);
6102   truelbl  = newiTempLabel(NULL);
6103   size = max(AOP_SIZE(left),AOP_SIZE(right));
6104
6105   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6106
6107   /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
6108    * POC_CPFSLT compare f, wreg, skip if f less then wreg */
6109   
6110
6111   /* if literal is on the right then swap with left */
6112   if ((AOP_TYPE(right) == AOP_LIT)) {
6113     operand *tmp = right ;
6114     unsigned long mask = (0x100 << (8*(size-1))) - 1;
6115
6116       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6117
6118 //      lit = (lit - 1) & mask;
6119       right = left;
6120       left = tmp;
6121       rFalseIfx.condition ^= 1;         /* reverse compare */
6122   } else
6123   if ((AOP_TYPE(left) == AOP_LIT)) {
6124     /* float compares are handled by support functions */
6125     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
6126   }
6127
6128
6129   //if(IC_TRUE(ifx) == NULL)
6130   /* if left & right are bit variables */
6131   if (AOP_TYPE(left) == AOP_CRY &&
6132       AOP_TYPE(right) == AOP_CRY ) {
6133
6134     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6135     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6136
6137   } else {
6138     symbol *lbl  = newiTempLabel(NULL);
6139
6140     if(AOP_TYPE(left) == AOP_LIT) {
6141       DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
6142
6143       if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6144         willCheckCarry = 1;
6145       else willCheckCarry = 0;
6146
6147       /* Special cases */
6148       if((lit == 0) && (sign == 0)) {
6149         /* unsigned compare to 0 */
6150         DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
6151         
6152         size--;
6153         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6154         while(size) 
6155           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
6156
6157         genSkipz2(&rFalseIfx,0);
6158         if(ifx)ifx->generated = 1;
6159         return;
6160       }
6161
6162       if(size==1) {
6163         /* Special cases */
6164         lit &= 0xff;
6165         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
6166           /* degenerate compare can never be true */
6167           if(rFalseIfx.condition == 0)
6168             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
6169
6170           if(ifx) ifx->generated = 1;
6171           return;
6172         }
6173
6174         if(sign) {
6175           /* signed comparisons to a literal byte */
6176           DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6177
6178           int lp1 = (lit+1) & 0xff;
6179
6180           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
6181           switch (lp1) {
6182           case 0:
6183             rFalseIfx.condition ^= 1;
6184             genSkipCond(&rFalseIfx,right,0,7);
6185             break;
6186           case 0x7f:
6187             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6188             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
6189             genSkipz2(&rFalseIfx,1);
6190             break;
6191           default:
6192             pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
6193             
6194             if(rFalseIfx.condition)
6195               pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
6196             else
6197               pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
6198
6199             if(willCheckCarry) {
6200               if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
6201               else { emitSETC; emitCLRC; }
6202               
6203             } else {
6204               pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6205             }              
6206                       
6207 /*          pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6208             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6209             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
6210             rFalseIfx.condition ^= 1;
6211             genSkipc(&rFalseIfx);
6212 */
6213             break;
6214           }
6215         } else {
6216           /* unsigned comparisons to a literal byte */
6217           DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6218
6219           switch(lit & 0xff ) {
6220                           /* special cases */
6221           case 0:
6222             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6223             genSkipz2(&rFalseIfx,0);
6224             break;
6225           case 0x7f:
6226             rFalseIfx.condition ^= 1;
6227             genSkipCond(&rFalseIfx,right,0,7);
6228             break;
6229           default:
6230             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
6231             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6232             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6233             rFalseIfx.condition ^= 1;
6234             if (AOP_TYPE(result) == AOP_CRY)
6235               genSkipc(&rFalseIfx);
6236             else {
6237               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6238               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6239             }         
6240             break;
6241           }
6242         }
6243
6244         if(ifx) ifx->generated = 1;
6245         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6246                 goto check_carry;
6247         return;
6248
6249       } else {
6250
6251         /* Size is greater than 1 */
6252
6253         if(sign) {
6254           int lp1 = lit+1;
6255
6256           size--;
6257
6258           if(lp1 == 0) {
6259             /* this means lit = 0xffffffff, or -1 */
6260
6261
6262             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
6263             rFalseIfx.condition ^= 1;
6264             genSkipCond(&rFalseIfx,right,size,7);
6265             if(ifx) ifx->generated = 1;
6266             return;
6267           }
6268
6269           if(lit == 0) {
6270             int s = size;
6271
6272             if(rFalseIfx.condition) {
6273               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6274               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6275             }
6276
6277             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6278             while(size--)
6279               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6280
6281
6282             emitSKPZ;
6283             if(rFalseIfx.condition) {
6284               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6285               pic16_emitpLabel(truelbl->key);
6286             }else {
6287               rFalseIfx.condition ^= 1;
6288               genSkipCond(&rFalseIfx,right,s,7);
6289             }
6290
6291             if(ifx) ifx->generated = 1;
6292             return;
6293           }
6294
6295           if((size == 1) &&  (0 == (lp1&0xff))) {
6296             /* lower byte of signed word is zero */
6297             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
6298             i = ((lp1 >> 8) & 0xff) ^0x80;
6299             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6300             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6301             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6302             rFalseIfx.condition ^= 1;
6303             genSkipc(&rFalseIfx);
6304
6305
6306             if(ifx) ifx->generated = 1;
6307             return;
6308           }
6309
6310           if(lit & (0x80 << (size*8))) {
6311             /* Lit is less than zero */
6312             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
6313             //rFalseIfx.condition ^= 1;
6314             //genSkipCond(&rFalseIfx,left,size,7);
6315             //rFalseIfx.condition ^= 1;
6316             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6317             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6318
6319             if(rFalseIfx.condition)
6320               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6321             else
6322               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6323
6324
6325           } else {
6326             /* Lit is greater than or equal to zero */
6327             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
6328             //rFalseIfx.condition ^= 1;
6329             //genSkipCond(&rFalseIfx,right,size,7);
6330             //rFalseIfx.condition ^= 1;
6331
6332             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6333             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6334
6335             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6336             if(rFalseIfx.condition)
6337               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6338             else
6339               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6340
6341           }
6342
6343
6344           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6345           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6346
6347           while(size--) {
6348
6349             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6350             emitSKPNZ;
6351             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6352           }
6353           rFalseIfx.condition ^= 1;
6354           //rFalseIfx.condition = 1;
6355           genSkipc(&rFalseIfx);
6356
6357           pic16_emitpLabel(truelbl->key);
6358
6359           if(ifx) ifx->generated = 1;
6360           return;
6361           // end of if (sign)
6362         } else {
6363
6364           /* compare word or long to an unsigned literal on the right.*/
6365
6366
6367           size--;
6368           if(lit < 0xff) {
6369             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6370             switch (lit) {
6371             case 0:
6372               break; /* handled above */
6373 /*
6374             case 0xff:
6375               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6376               while(size--)
6377                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6378               genSkipz2(&rFalseIfx,0);
6379               break;
6380 */
6381             default:
6382               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6383               while(--size)
6384                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6385
6386               emitSKPZ;
6387               if(rFalseIfx.condition)
6388                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6389               else
6390                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6391
6392
6393               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6394               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6395
6396               rFalseIfx.condition ^= 1;
6397               genSkipc(&rFalseIfx);
6398             }
6399
6400             pic16_emitpLabel(truelbl->key);
6401
6402             if(ifx) ifx->generated = 1;
6403             return;
6404           }
6405
6406
6407           lit++;
6408           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6409           i = (lit >> (size*8)) & 0xff;
6410
6411           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6412           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6413
6414           while(size--) {
6415             i = (lit >> (size*8)) & 0xff;
6416
6417             if(i) {
6418               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6419               emitSKPNZ;
6420               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6421             } else {
6422               /* this byte of the lit is zero, 
6423                * if it's not the last then OR in the variable */
6424               if(size)
6425                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6426             }
6427           }
6428
6429
6430           pic16_emitpLabel(lbl->key);
6431
6432           rFalseIfx.condition ^= 1;
6433
6434           genSkipc(&rFalseIfx);
6435         }
6436
6437         if(sign)
6438           pic16_emitpLabel(truelbl->key);
6439         if(ifx) ifx->generated = 1;
6440         return;
6441       }
6442     }
6443     /* Compare two variables */
6444
6445     DEBUGpic16_emitcode(";sign","%d",sign);
6446
6447     size--;
6448     if(sign) {
6449       /* Sigh. thus sucks... */
6450       if(size) {
6451         pCodeOp *pctemp;
6452         
6453         pctemp = pic16_popGetTempReg(1);
6454         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6455         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6456         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6457         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6458         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6459         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6460         pic16_popReleaseTempReg(pctemp, 1);
6461       } else {
6462         /* Signed char comparison */
6463         /* Special thanks to Nikolai Golovchenko for this snippet */
6464         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6465         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6466         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
6467         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6468         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6469         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6470
6471         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6472         genSkipc(&rFalseIfx);
6473           
6474         if(ifx) ifx->generated = 1;
6475         return;
6476       }
6477
6478     } else {
6479
6480       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6481       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6482     }
6483
6484
6485     /* The rest of the bytes of a multi-byte compare */
6486     while (size) {
6487
6488       emitSKPZ;
6489       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
6490       size--;
6491
6492       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6493       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6494
6495
6496     }
6497
6498     pic16_emitpLabel(lbl->key);
6499
6500     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6501     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
6502         (AOP_TYPE(result) == AOP_REG)) {
6503       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6504       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6505     } else {
6506       genSkipc(&rFalseIfx);
6507     }         
6508     //genSkipc(&rFalseIfx);
6509     if(ifx) ifx->generated = 1;
6510
6511     return;
6512
6513   }
6514
6515 check_carry:
6516   if ((AOP_TYPE(result) != AOP_CRY) 
6517         && AOP_SIZE(result)) {
6518     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6519
6520     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6521
6522     pic16_outBitC(result);
6523   } else {
6524     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6525     /* if the result is used in the next
6526        ifx conditional branch then generate
6527        code a little differently */
6528     if (ifx )
6529       genIfxJump (ifx,"c");
6530     else
6531       pic16_outBitC(result);
6532     /* leave the result in acc */
6533   }
6534
6535 }
6536 #endif  /* } */
6537
6538
6539 #endif  /* } */
6540
6541
6542
6543 /*-----------------------------------------------------------------*/
6544 /* genCmpGt :- greater than comparison                             */
6545 /*-----------------------------------------------------------------*/
6546 static void genCmpGt (iCode *ic, iCode *ifx)
6547 {
6548   operand *left, *right, *result;
6549   sym_link *letype , *retype;
6550   int sign ;
6551
6552     FENTRY;
6553     
6554     left = IC_LEFT(ic);
6555     right= IC_RIGHT(ic);
6556     result = IC_RESULT(ic);
6557
6558     letype = getSpec(operandType(left));
6559     retype =getSpec(operandType(right));
6560     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6561     /* assign the amsops */
6562     pic16_aopOp (left,ic,FALSE);
6563     pic16_aopOp (right,ic,FALSE);
6564     pic16_aopOp (result,ic,TRUE);
6565
6566     genCmp(right, left, result, ifx, sign);
6567
6568     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6569     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6570     pic16_freeAsmop(result,NULL,ic,TRUE); 
6571 }
6572
6573 /*-----------------------------------------------------------------*/
6574 /* genCmpLt - less than comparisons                                */
6575 /*-----------------------------------------------------------------*/
6576 static void genCmpLt (iCode *ic, iCode *ifx)
6577 {
6578   operand *left, *right, *result;
6579   sym_link *letype , *retype;
6580   int sign ;
6581
6582     FENTRY;
6583
6584     left = IC_LEFT(ic);
6585     right= IC_RIGHT(ic);
6586     result = IC_RESULT(ic);
6587
6588     letype = getSpec(operandType(left));
6589     retype =getSpec(operandType(right));
6590     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6591
6592     /* assign the amsops */
6593     pic16_aopOp (left,ic,FALSE);
6594     pic16_aopOp (right,ic,FALSE);
6595     pic16_aopOp (result,ic,TRUE);
6596
6597     genCmp(left, right, result, ifx, sign);
6598
6599     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6600     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6601     pic16_freeAsmop(result,NULL,ic,TRUE); 
6602 }
6603
6604 #if 0
6605 // not needed ATM
6606 // FIXME reenable literal optimisation when the pic16 port is stable
6607
6608 /*-----------------------------------------------------------------*/
6609 /* genc16bit2lit - compare a 16 bit value to a literal             */
6610 /*-----------------------------------------------------------------*/
6611 static void genc16bit2lit(operand *op, int lit, int offset)
6612 {
6613   int i;
6614
6615   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6616   if( (lit&0xff) == 0) 
6617     i=1;
6618   else
6619     i=0;
6620
6621   switch( BYTEofLONG(lit,i)) { 
6622   case 0:
6623     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6624     break;
6625   case 1:
6626     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6627     break;
6628   case 0xff:
6629     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6630     break;
6631   default:
6632     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6633     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6634   }
6635
6636   i ^= 1;
6637
6638   switch( BYTEofLONG(lit,i)) { 
6639   case 0:
6640     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6641     break;
6642   case 1:
6643     emitSKPNZ;
6644     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6645     break;
6646   case 0xff:
6647     emitSKPNZ;
6648     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6649     break;
6650   default:
6651     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6652     emitSKPNZ;
6653     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6654
6655   }
6656
6657 }
6658 #endif
6659
6660 #if 0
6661 // not needed ATM
6662 /*-----------------------------------------------------------------*/
6663 /* gencjneshort - compare and jump if not equal                    */
6664 /*-----------------------------------------------------------------*/
6665 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6666 {
6667   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6668   int offset = 0;
6669   int res_offset = 0;  /* the result may be a different size then left or right */
6670   int res_size = AOP_SIZE(result);
6671   resolvedIfx rIfx;
6672   symbol *lbl, *lbl_done;
6673
6674   unsigned long lit = 0L;
6675   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6676
6677   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6678   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6679   if(result)
6680     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6681   resolveIfx(&rIfx,ifx);
6682   lbl =  newiTempLabel(NULL);
6683   lbl_done =  newiTempLabel(NULL);
6684
6685
6686   /* if the left side is a literal or 
6687      if the right is in a pointer register and left 
6688      is not */
6689   if ((AOP_TYPE(left) == AOP_LIT) || 
6690       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6691     operand *t = right;
6692     right = left;
6693     left = t;
6694   }
6695   if(AOP_TYPE(right) == AOP_LIT)
6696     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6697
6698   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6699     preserve_result = 1;
6700
6701   if(result && !preserve_result)
6702     {
6703       int i;
6704       for(i = 0; i < AOP_SIZE(result); i++)
6705         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6706     }
6707
6708
6709   /* if the right side is a literal then anything goes */
6710   if (AOP_TYPE(right) == AOP_LIT &&
6711       AOP_TYPE(left) != AOP_DIR ) {
6712     switch(size) {
6713     case 2:
6714       genc16bit2lit(left, lit, 0);
6715       emitSKPZ;
6716       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6717       break;
6718     default:
6719       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6720       while (size--) {
6721         if(lit & 0xff) {
6722           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6723           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6724         } else {
6725           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6726         }
6727
6728         emitSKPZ;
6729         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6730         offset++;
6731         if(res_offset < res_size-1)
6732           res_offset++;
6733         lit >>= 8;
6734       }
6735       break;
6736     }
6737   }
6738
6739   /* if the right side is in a register or in direct space or
6740      if the left is a pointer register & right is not */    
6741   else if (AOP_TYPE(right) == AOP_REG ||
6742            AOP_TYPE(right) == AOP_DIR || 
6743            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6744            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6745     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6746     int lbl_key = lbl->key;
6747
6748     if(result) {
6749       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6750       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6751     }else {
6752       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6753       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6754               __FUNCTION__,__LINE__);
6755       return;
6756     }
6757    
6758 /*     switch(size) { */
6759 /*     case 2: */
6760 /*       genc16bit2lit(left, lit, 0); */
6761 /*       emitSKPNZ; */
6762 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6763 /*       break; */
6764 /*     default: */
6765     while (size--) {
6766       int emit_skip=1;
6767       if((AOP_TYPE(left) == AOP_DIR) && 
6768          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6769
6770         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6771         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6772
6773       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6774             
6775         switch (lit & 0xff) {
6776         case 0:
6777           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6778           break;
6779         case 1:
6780           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6781           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6782           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6783           emit_skip=0;
6784           break;
6785         case 0xff:
6786           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6787           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6788           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6789           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6790           emit_skip=0;
6791           break;
6792         default:
6793           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6794           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6795         }
6796         lit >>= 8;
6797
6798       } else {
6799         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6800       }
6801       if(emit_skip) {
6802         if(AOP_TYPE(result) == AOP_CRY) {
6803           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6804           if(rIfx.condition)
6805             emitSKPNZ;
6806           else
6807             emitSKPZ;
6808           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6809         } else {
6810           /* fix me. probably need to check result size too */
6811           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6812           if(rIfx.condition)
6813             emitSKPZ;
6814           else
6815             emitSKPNZ;
6816           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6817           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6818         }
6819         if(ifx)
6820           ifx->generated=1;
6821       }
6822       emit_skip++;
6823       offset++;
6824       if(res_offset < res_size-1)
6825         res_offset++;
6826     }
6827 /*       break; */
6828 /*     } */
6829   } else if(AOP_TYPE(right) == AOP_REG &&
6830             AOP_TYPE(left) != AOP_DIR){
6831
6832     while(size--) {
6833       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6834       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6835       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6836       if(rIfx.condition)
6837         emitSKPNZ;
6838       else
6839         emitSKPZ;
6840       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6841       offset++;
6842       if(res_offset < res_size-1)
6843         res_offset++;
6844     }
6845       
6846   }else{
6847     /* right is a pointer reg need both a & b */
6848     while(size--) {
6849       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6850       if(strcmp(l,"b"))
6851         pic16_emitcode("mov","b,%s",l);
6852       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6853       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6854       offset++;
6855     }
6856   }
6857
6858   if(result && preserve_result)
6859     {
6860       int i;
6861       for(i = 0; i < AOP_SIZE(result); i++)
6862         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6863     }
6864
6865   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6866
6867   if(result && preserve_result)
6868     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6869
6870   if(!rIfx.condition)
6871     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6872
6873   pic16_emitpLabel(lbl->key);
6874
6875   if(result && preserve_result)
6876     {
6877       int i;
6878       for(i = 0; i < AOP_SIZE(result); i++)
6879         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6880
6881       pic16_emitpLabel(lbl_done->key);
6882    }
6883
6884   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6885
6886   if(ifx)
6887     ifx->generated = 1;
6888 }
6889 #endif
6890
6891 #if 0
6892 /*-----------------------------------------------------------------*/
6893 /* gencjne - compare and jump if not equal                         */
6894 /*-----------------------------------------------------------------*/
6895 static void gencjne(operand *left, operand *right, iCode *ifx)
6896 {
6897     symbol *tlbl  = newiTempLabel(NULL);
6898
6899     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6900     gencjneshort(left, right, lbl);
6901
6902     pic16_emitcode("mov","a,%s",one);
6903     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6904     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6905     pic16_emitcode("clr","a");
6906     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6907
6908     pic16_emitpLabel(lbl->key);
6909     pic16_emitpLabel(tlbl->key);
6910
6911 }
6912 #endif
6913
6914
6915 /*-----------------------------------------------------------------*/
6916 /* is_LitOp - check if operand has to be treated as literal        */
6917 /*-----------------------------------------------------------------*/
6918 static bool is_LitOp(operand *op)
6919 {
6920   return ((AOP_TYPE(op) == AOP_LIT)
6921       || ( (AOP_TYPE(op) == AOP_PCODE)
6922           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6923               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6924 }
6925
6926 /*-----------------------------------------------------------------*/
6927 /* is_LitAOp - check if operand has to be treated as literal        */
6928 /*-----------------------------------------------------------------*/
6929 static bool is_LitAOp(asmop *aop)
6930 {
6931   return ((aop->type == AOP_LIT)
6932       || ( (aop->type == AOP_PCODE)
6933           && ( (aop->aopu.pcop->type == PO_LITERAL)
6934               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6935 }
6936
6937
6938
6939 /*-----------------------------------------------------------------*/
6940 /* genCmpEq - generates code for equal to                          */
6941 /*-----------------------------------------------------------------*/
6942 static void genCmpEq (iCode *ic, iCode *ifx)
6943 {
6944   operand *left, *right, *result;
6945   symbol *falselbl = newiTempLabel(NULL);
6946   symbol *donelbl = newiTempLabel(NULL);
6947
6948   int preserve_result = 0;
6949   int generate_result = 0;
6950   int i=0;
6951
6952   FENTRY;
6953   
6954   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6955   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6956   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6957  
6958   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6959
6960   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6961     {
6962       werror(W_POSSBUG2, __FILE__, __LINE__);
6963       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6964       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6965       goto release;
6966     }
6967
6968   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6969     {
6970       operand *tmp = right ;
6971       right = left;
6972       left = tmp;
6973     }
6974
6975   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6976     preserve_result = 1;
6977
6978   if(result && AOP_SIZE(result))
6979     generate_result = 1;
6980
6981   if(generate_result && !preserve_result)
6982     {
6983       for(i = 0; i < AOP_SIZE(result); i++)
6984         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6985     }
6986
6987   for(i=0; i < AOP_SIZE(left); i++)
6988     {
6989       if(AOP_TYPE(left) != AOP_ACC)
6990         {
6991           if(is_LitOp(left))
6992             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6993           else
6994             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6995         }
6996       if(is_LitOp(right))
6997         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6998       else
6999         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
7000
7001       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
7002     }
7003
7004   // result == true
7005
7006   if(generate_result && preserve_result)
7007     {
7008       for(i = 0; i < AOP_SIZE(result); i++)
7009         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7010     }
7011
7012   if(generate_result)
7013     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7014
7015   if(generate_result && preserve_result)
7016     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7017
7018   if(ifx && IC_TRUE(ifx))
7019     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7020
7021   if(ifx && IC_FALSE(ifx))
7022     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7023
7024   pic16_emitpLabel(falselbl->key);
7025
7026   // result == false
7027
7028   if(ifx && IC_FALSE(ifx))
7029     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7030
7031   if(generate_result && preserve_result)
7032     {
7033       for(i = 0; i < AOP_SIZE(result); i++)
7034         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7035     }
7036
7037   pic16_emitpLabel(donelbl->key);
7038
7039   if(ifx)
7040     ifx->generated = 1;
7041
7042 release:
7043   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7044   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7045   pic16_freeAsmop(result,NULL,ic,TRUE);
7046
7047 }
7048
7049
7050 #if 0
7051 // old version kept for reference
7052
7053 /*-----------------------------------------------------------------*/
7054 /* genCmpEq - generates code for equal to                          */
7055 /*-----------------------------------------------------------------*/
7056 static void genCmpEq (iCode *ic, iCode *ifx)
7057 {
7058     operand *left, *right, *result;
7059     unsigned long lit = 0L;
7060     int size,offset=0;
7061     symbol *falselbl  = newiTempLabel(NULL);
7062
7063
7064     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7065
7066     if(ifx)
7067       DEBUGpic16_emitcode ("; ifx is non-null","");
7068     else
7069       DEBUGpic16_emitcode ("; ifx is null","");
7070
7071     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7072     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7073     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7074
7075     size = max(AOP_SIZE(left),AOP_SIZE(right));
7076
7077     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7078
7079     /* if literal, literal on the right or 
7080     if the right is in a pointer register and left 
7081     is not */
7082     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
7083         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7084       operand *tmp = right ;
7085       right = left;
7086       left = tmp;
7087     }
7088
7089
7090     if(ifx && !AOP_SIZE(result)){
7091         symbol *tlbl;
7092         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
7093         /* if they are both bit variables */
7094         if (AOP_TYPE(left) == AOP_CRY &&
7095             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7096                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
7097             if(AOP_TYPE(right) == AOP_LIT){
7098                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7099                 if(lit == 0L){
7100                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7101                     pic16_emitcode("cpl","c");
7102                 } else if(lit == 1L) {
7103                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7104                 } else {
7105                     pic16_emitcode("clr","c");
7106                 }
7107                 /* AOP_TYPE(right) == AOP_CRY */
7108             } else {
7109                 symbol *lbl = newiTempLabel(NULL);
7110                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7111                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7112                 pic16_emitcode("cpl","c");
7113                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7114             }
7115             /* if true label then we jump if condition
7116             supplied is true */
7117             tlbl = newiTempLabel(NULL);
7118             if ( IC_TRUE(ifx) ) {
7119                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7120                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7121             } else {
7122                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7123                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7124             }
7125             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7126
7127                 {
7128                 /* left and right are both bit variables, result is carry */
7129                         resolvedIfx rIfx;
7130               
7131                         resolveIfx(&rIfx,ifx);
7132
7133                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7134                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7135                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7136                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7137                         genSkipz2(&rIfx,0);
7138                 }
7139         } else {
7140
7141                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
7142
7143                         /* They're not both bit variables. Is the right a literal? */
7144                         if(AOP_TYPE(right) == AOP_LIT) {
7145                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7146             
7147                         switch(size) {
7148
7149                                 case 1:
7150                                         switch(lit & 0xff) {
7151                                                 case 1:
7152                                                                 if ( IC_TRUE(ifx) ) {
7153                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7154                                                                         emitSKPNZ;
7155                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7156                                                                 } else {
7157                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7158                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7159                                                                 }
7160                                                                 break;
7161                                                 case 0xff:
7162                                                                 if ( IC_TRUE(ifx) ) {
7163                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7164                                                                         emitSKPNZ;
7165                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7166                                                                 } else {
7167                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7168                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7169                                                                 }
7170                                                                 break;
7171                                                 default:
7172                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7173                                                                 if(lit)
7174                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7175                                                                 genSkip(ifx,'z');
7176                                         } // switch lit
7177
7178
7179                                         /* end of size == 1 */
7180                                         break;
7181               
7182                                 case 2:
7183                                         genc16bit2lit(left,lit,offset);
7184                                         genSkip(ifx,'z');
7185                                         break;
7186                                         /* end of size == 2 */
7187
7188                                 default:
7189                                         /* size is 4 */
7190                                         if(lit==0) {
7191                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7192                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7193                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7194                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7195                                                 genSkip(ifx,'z');
7196                                         } else {
7197                                                 /* search for patterns that can be optimized */
7198
7199                                                 genc16bit2lit(left,lit,0);
7200                                                 lit >>= 16;
7201                                                 if(lit) {
7202                                                                 if(IC_TRUE(ifx))
7203                                                                 emitSKPZ; // if hi word unequal
7204                                                                 else
7205                                                                 emitSKPNZ; // if hi word equal
7206                                                                 // fail early
7207                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7208                                                         genc16bit2lit(left,lit,2);
7209                                                         genSkip(ifx,'z');
7210                                                 } else {
7211                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7212                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7213                                                         genSkip(ifx,'z');
7214                                                 }
7215                                         }
7216                                                 pic16_emitpLabel(falselbl->key);
7217                                                 break;
7218
7219                         } // switch size
7220           
7221                         ifx->generated = 1;
7222                         goto release ;
7223             
7224
7225           } else if(AOP_TYPE(right) == AOP_CRY ) {
7226             /* we know the left is not a bit, but that the right is */
7227             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7228             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7229                       pic16_popGet(AOP(right),offset));
7230             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7231
7232             /* if the two are equal, then W will be 0 and the Z bit is set
7233              * we could test Z now, or go ahead and check the high order bytes if
7234              * the variable we're comparing is larger than a byte. */
7235
7236             while(--size)
7237               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7238
7239             if ( IC_TRUE(ifx) ) {
7240               emitSKPNZ;
7241               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7242               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7243             } else {
7244               emitSKPZ;
7245               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7246               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7247             }
7248
7249           } else {
7250             /* They're both variables that are larger than bits */
7251             int s = size;
7252
7253             tlbl = newiTempLabel(NULL);
7254
7255             while(size--) {
7256               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7257               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7258
7259               if ( IC_TRUE(ifx) ) {
7260                 if(size) {
7261                   emitSKPZ;
7262                 
7263                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7264
7265                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7266                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7267                 } else {
7268                   emitSKPNZ;
7269
7270                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7271
7272
7273                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7274                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7275                 }
7276               } else {
7277                 emitSKPZ;
7278
7279                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7280
7281                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7282                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7283               }
7284               offset++;
7285             }
7286             if(s>1 && IC_TRUE(ifx)) {
7287               pic16_emitpLabel(tlbl->key);
7288               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7289             }
7290           }
7291         }
7292         /* mark the icode as generated */
7293         ifx->generated = 1;
7294         goto release ;
7295     }
7296
7297     /* if they are both bit variables */
7298     if (AOP_TYPE(left) == AOP_CRY &&
7299         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7300         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7301         if(AOP_TYPE(right) == AOP_LIT){
7302             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7303             if(lit == 0L){
7304                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7305                 pic16_emitcode("cpl","c");
7306             } else if(lit == 1L) {
7307                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7308             } else {
7309                 pic16_emitcode("clr","c");
7310             }
7311             /* AOP_TYPE(right) == AOP_CRY */
7312         } else {
7313             symbol *lbl = newiTempLabel(NULL);
7314             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7315             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7316             pic16_emitcode("cpl","c");
7317             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7318         }
7319         /* c = 1 if egal */
7320         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7321             pic16_outBitC(result);
7322             goto release ;
7323         }
7324         if (ifx) {
7325             genIfxJump (ifx,"c");
7326             goto release ;
7327         }
7328         /* if the result is used in an arithmetic operation
7329         then put the result in place */
7330         pic16_outBitC(result);
7331     } else {
7332       
7333       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7334       gencjne(left,right,result,ifx);
7335 /*
7336       if(ifx) 
7337         gencjne(left,right,newiTempLabel(NULL));
7338       else {
7339         if(IC_TRUE(ifx)->key)
7340           gencjne(left,right,IC_TRUE(ifx)->key);
7341         else
7342           gencjne(left,right,IC_FALSE(ifx)->key);
7343         ifx->generated = 1;
7344         goto release ;
7345       }
7346       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7347         pic16_aopPut(AOP(result),"a",0);
7348         goto release ;
7349       }
7350
7351       if (ifx) {
7352         genIfxJump (ifx,"a");
7353         goto release ;
7354       }
7355 */
7356       /* if the result is used in an arithmetic operation
7357          then put the result in place */
7358 /*
7359       if (AOP_TYPE(result) != AOP_CRY) 
7360         pic16_outAcc(result);
7361 */
7362       /* leave the result in acc */
7363     }
7364
7365 release:
7366     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7367     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7368     pic16_freeAsmop(result,NULL,ic,TRUE);
7369 }
7370 #endif
7371
7372 /*-----------------------------------------------------------------*/
7373 /* ifxForOp - returns the icode containing the ifx for operand     */
7374 /*-----------------------------------------------------------------*/
7375 static iCode *ifxForOp ( operand *op, iCode *ic )
7376 {
7377   FENTRY2;
7378
7379     /* if true symbol then needs to be assigned */
7380     if (IS_TRUE_SYMOP(op))
7381         return NULL ;
7382
7383     /* if this has register type condition and
7384     the next instruction is ifx with the same operand
7385     and live to of the operand is upto the ifx only then */
7386     if (ic->next
7387         && ic->next->op == IFX
7388         && IC_COND(ic->next)->key == op->key
7389         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7390         ) {
7391                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7392           return ic->next;
7393     }
7394
7395     /*
7396     if (ic->next &&
7397         ic->next->op == IFX &&
7398         IC_COND(ic->next)->key == op->key) {
7399       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7400       return ic->next;
7401     }
7402     */
7403
7404     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7405     if (ic->next &&
7406         ic->next->op == IFX)
7407       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7408
7409     if (ic->next &&
7410         ic->next->op == IFX &&
7411         IC_COND(ic->next)->key == op->key) {
7412       DEBUGpic16_emitcode ("; "," key is okay");
7413       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7414                            OP_SYMBOL(op)->liveTo,
7415                            ic->next->seq);
7416     }
7417
7418 #if 0
7419     /* the code below is completely untested
7420      * it just allows ulong2fs.c compile -- VR */
7421          
7422     ic = ic->next;
7423     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7424                                         __FILE__, __FUNCTION__, __LINE__);
7425         
7426     /* if this has register type condition and
7427     the next instruction is ifx with the same operand
7428     and live to of the operand is upto the ifx only then */
7429     if (ic->next &&
7430         ic->next->op == IFX &&
7431         IC_COND(ic->next)->key == op->key &&
7432         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7433         return ic->next;
7434
7435     if (ic->next &&
7436         ic->next->op == IFX &&
7437         IC_COND(ic->next)->key == op->key) {
7438       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7439       return ic->next;
7440     }
7441
7442     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7443                                         __FILE__, __FUNCTION__, __LINE__);
7444
7445 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7446 #endif
7447
7448     return NULL;
7449 }
7450 /*-----------------------------------------------------------------*/
7451 /* genAndOp - for && operation                                     */
7452 /*-----------------------------------------------------------------*/
7453 static void genAndOp (iCode *ic)
7454 {
7455   operand *left,*right, *result;
7456 /*     symbol *tlbl; */
7457
7458     FENTRY;
7459
7460     /* note here that && operations that are in an
7461     if statement are taken away by backPatchLabels
7462     only those used in arthmetic operations remain */
7463     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7464     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7465     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7466
7467     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7468
7469     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7470     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7471     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7472
7473     /* if both are bit variables */
7474 /*     if (AOP_TYPE(left) == AOP_CRY && */
7475 /*         AOP_TYPE(right) == AOP_CRY ) { */
7476 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7477 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7478 /*         pic16_outBitC(result); */
7479 /*     } else { */
7480 /*         tlbl = newiTempLabel(NULL); */
7481 /*         pic16_toBoolean(left);     */
7482 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7483 /*         pic16_toBoolean(right); */
7484 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7485 /*         pic16_outBitAcc(result); */
7486 /*     } */
7487
7488     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7489     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7490     pic16_freeAsmop(result,NULL,ic,TRUE);
7491 }
7492
7493
7494 /*-----------------------------------------------------------------*/
7495 /* genOrOp - for || operation                                      */
7496 /*-----------------------------------------------------------------*/
7497 /*
7498   tsd pic port -
7499   modified this code, but it doesn't appear to ever get called
7500 */
7501
7502 static void genOrOp (iCode *ic)
7503 {
7504   operand *left,*right, *result;
7505   symbol *tlbl;
7506
7507     FENTRY;  
7508
7509   /* note here that || operations that are in an
7510     if statement are taken away by backPatchLabels
7511     only those used in arthmetic operations remain */
7512     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7513     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7514     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7515
7516     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7517
7518     /* if both are bit variables */
7519     if (AOP_TYPE(left) == AOP_CRY &&
7520         AOP_TYPE(right) == AOP_CRY ) {
7521       pic16_emitcode("clrc","");
7522       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7523                AOP(left)->aopu.aop_dir,
7524                AOP(left)->aopu.aop_dir);
7525       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7526                AOP(right)->aopu.aop_dir,
7527                AOP(right)->aopu.aop_dir);
7528       pic16_emitcode("setc","");
7529
7530     } else {
7531         tlbl = newiTempLabel(NULL);
7532         pic16_toBoolean(left);
7533         emitSKPZ;
7534         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7535         pic16_toBoolean(right);
7536         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7537
7538         pic16_outBitAcc(result);
7539     }
7540
7541     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7542     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7543     pic16_freeAsmop(result,NULL,ic,TRUE);            
7544 }
7545
7546 /*-----------------------------------------------------------------*/
7547 /* isLiteralBit - test if lit == 2^n                               */
7548 /*-----------------------------------------------------------------*/
7549 static int isLiteralBit(unsigned long lit)
7550 {
7551     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7552     0x100L,0x200L,0x400L,0x800L,
7553     0x1000L,0x2000L,0x4000L,0x8000L,
7554     0x10000L,0x20000L,0x40000L,0x80000L,
7555     0x100000L,0x200000L,0x400000L,0x800000L,
7556     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7557     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7558     int idx;
7559     
7560     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7561     for(idx = 0; idx < 32; idx++)
7562         if(lit == pw[idx])
7563             return idx+1;
7564     return 0;
7565 }
7566
7567 /*-----------------------------------------------------------------*/
7568 /* continueIfTrue -                                                */
7569 /*-----------------------------------------------------------------*/
7570 static void continueIfTrue (iCode *ic)
7571 {
7572   FENTRY;
7573   if(IC_TRUE(ic))
7574     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7575   ic->generated = 1;
7576 }
7577
7578 /*-----------------------------------------------------------------*/
7579 /* jmpIfTrue -                                                     */
7580 /*-----------------------------------------------------------------*/
7581 static void jumpIfTrue (iCode *ic)
7582 {
7583   FENTRY;
7584   if(!IC_TRUE(ic))
7585     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7586   ic->generated = 1;
7587 }
7588
7589 /*-----------------------------------------------------------------*/
7590 /* jmpTrueOrFalse -                                                */
7591 /*-----------------------------------------------------------------*/
7592 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7593 {
7594   // ugly but optimized by peephole
7595   FENTRY;
7596   if(IC_TRUE(ic)){
7597     symbol *nlbl = newiTempLabel(NULL);
7598       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7599       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7600       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7601       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7602   } else {
7603     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7604     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7605   }
7606   ic->generated = 1;
7607 }
7608
7609 /*-----------------------------------------------------------------*/
7610 /* genAnd  - code for and                                          */
7611 /*-----------------------------------------------------------------*/
7612 static void genAnd (iCode *ic, iCode *ifx)
7613 {
7614   operand *left, *right, *result;
7615   int size, offset=0;  
7616   unsigned long lit = 0L;
7617   int bytelit = 0;
7618   resolvedIfx rIfx;
7619
7620     FENTRY;
7621     
7622   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7623   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7624   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7625
7626   resolveIfx(&rIfx,ifx);
7627
7628   /* if left is a literal & right is not then exchange them */
7629   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7630       AOP_NEEDSACC(left)) {
7631     operand *tmp = right ;
7632     right = left;
7633     left = tmp;
7634   }
7635
7636   /* if result = right then exchange them */
7637   if(pic16_sameRegs(AOP(result),AOP(right))){
7638     operand *tmp = right ;
7639     right = left;
7640     left = tmp;
7641   }
7642
7643   /* if right is bit then exchange them */
7644   if (AOP_TYPE(right) == AOP_CRY &&
7645       AOP_TYPE(left) != AOP_CRY){
7646     operand *tmp = right ;
7647     right = left;
7648     left = tmp;
7649   }
7650   if(AOP_TYPE(right) == AOP_LIT)
7651     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7652
7653   size = AOP_SIZE(result);
7654
7655   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7656
7657   // if(bit & yy)
7658   // result = bit & yy;
7659   if (AOP_TYPE(left) == AOP_CRY){
7660     // c = bit & literal;
7661     if(AOP_TYPE(right) == AOP_LIT){
7662       if(lit & 1) {
7663         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7664           // no change
7665           goto release;
7666         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7667       } else {
7668         // bit(result) = 0;
7669         if(size && (AOP_TYPE(result) == AOP_CRY)){
7670           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7671           goto release;
7672         }
7673         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7674           jumpIfTrue(ifx);
7675           goto release;
7676         }
7677         pic16_emitcode("clr","c");
7678       }
7679     } else {
7680       if (AOP_TYPE(right) == AOP_CRY){
7681         // c = bit & bit;
7682         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7683         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7684       } else {
7685         // c = bit & val;
7686         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7687         // c = lsb
7688         pic16_emitcode("rrc","a");
7689         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7690       }
7691     }
7692     // bit = c
7693     // val = c
7694     if(size)
7695       pic16_outBitC(result);
7696     // if(bit & ...)
7697     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7698       genIfxJump(ifx, "c");           
7699     goto release ;
7700   }
7701
7702   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7703   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7704   if((AOP_TYPE(right) == AOP_LIT) &&
7705      (AOP_TYPE(result) == AOP_CRY) &&
7706      (AOP_TYPE(left) != AOP_CRY)){
7707     int posbit = isLiteralBit(lit);
7708     /* left &  2^n */
7709     if(posbit){
7710       posbit--;
7711       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7712       // bit = left & 2^n
7713       if(size)
7714         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7715       // if(left &  2^n)
7716       else{
7717         if(ifx){
7718 /*
7719           if(IC_TRUE(ifx)) {
7720             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7721             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7722           } else {
7723             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7724             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7725           }
7726 */
7727         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7728         size = AOP_SIZE(left);
7729
7730         {
7731           int bp = posbit, ofs=0;
7732           
7733             while(bp > 7) {
7734               bp -= 8;
7735               ofs++;
7736             }
7737         
7738           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7739                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7740
7741         }
7742 /*
7743           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7744                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7745 */
7746           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7747           
7748           ifx->generated = 1;
7749         }
7750         goto release;
7751       }
7752     } else {
7753       symbol *tlbl = newiTempLabel(NULL);
7754       int sizel = AOP_SIZE(left);
7755
7756       if(size)
7757         emitSETC;
7758
7759       while(sizel--) {
7760         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7761
7762           /* patch provided by Aaron Colwell */
7763           if((posbit = isLiteralBit(bytelit)) != 0) {
7764               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7765                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7766                                                 (posbit-1),0, PO_GPR_REGISTER));
7767
7768               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7769 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7770           } else {
7771               if (bytelit == 0xff) {
7772                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7773                    * a peephole could optimize it out -- VR */
7774                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7775               } else {
7776                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7777                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7778               }
7779
7780               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7781                             pic16_popGetLabel(tlbl->key));
7782           }
7783         
7784 #if 0
7785           /* old code, left here for reference -- VR 09/2004 */
7786           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7787           // byte ==  2^n ?
7788           if((posbit = isLiteralBit(bytelit)) != 0)
7789             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7790           else{
7791             if(bytelit != 0x0FFL)
7792               pic16_emitcode("anl","a,%s",
7793                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7794             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7795           }
7796 #endif
7797         }
7798         offset++;
7799       }
7800       // bit = left & literal
7801       if(size) {
7802         emitCLRC;
7803         pic16_emitpLabel(tlbl->key);
7804       }
7805       // if(left & literal)
7806       else {
7807         if(ifx) {
7808           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7809           ifx->generated = 1;
7810         }
7811         pic16_emitpLabel(tlbl->key);
7812         goto release;
7813       }
7814     }
7815
7816     pic16_outBitC(result);
7817     goto release ;
7818   }
7819
7820   /* if left is same as result */
7821   if(pic16_sameRegs(AOP(result),AOP(left))){
7822     int know_W = -1;
7823     for(;size--; offset++,lit>>=8) {
7824       if(AOP_TYPE(right) == AOP_LIT){
7825         switch(lit & 0xff) {
7826         case 0x00:
7827           /*  and'ing with 0 has clears the result */
7828 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7829           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7830           break;
7831         case 0xff:
7832           /* and'ing with 0xff is a nop when the result and left are the same */
7833           break;
7834
7835         default:
7836           {
7837             int p = pic16_my_powof2( (~lit) & 0xff );
7838             if(p>=0) {
7839               /* only one bit is set in the literal, so use a bcf instruction */
7840 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7841               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7842
7843             } else {
7844               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7845               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7846               if(know_W != (lit&0xff))
7847                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7848               know_W = lit &0xff;
7849               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7850             }
7851           }    
7852         }
7853       } else {
7854         if (AOP_TYPE(left) == AOP_ACC) {
7855           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7856         } else {                    
7857           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7858           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7859
7860         }
7861       }
7862     }
7863
7864   } else {
7865     // left & result in different registers
7866     if(AOP_TYPE(result) == AOP_CRY){
7867       // result = bit
7868       // if(size), result in bit
7869       // if(!size && ifx), conditional oper: if(left & right)
7870       symbol *tlbl = newiTempLabel(NULL);
7871       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7872       if(size)
7873         pic16_emitcode("setb","c");
7874       while(sizer--){
7875         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7876         pic16_emitcode("anl","a,%s",
7877                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7878         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7879         offset++;
7880       }
7881       if(size){
7882         CLRC;
7883         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7884         pic16_outBitC(result);
7885       } else if(ifx)
7886         jmpTrueOrFalse(ifx, tlbl);
7887     } else {
7888       for(;(size--);offset++) {
7889         // normal case
7890         // result = left & right
7891         if(AOP_TYPE(right) == AOP_LIT){
7892           int t = (lit >> (offset*8)) & 0x0FFL;
7893           switch(t) { 
7894           case 0x00:
7895             pic16_emitcode("clrf","%s",
7896                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7897             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7898             break;
7899           case 0xff:
7900             pic16_emitcode("movf","%s,w",
7901                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7902             pic16_emitcode("movwf","%s",
7903                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7904             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7905             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7906             break;
7907           default:
7908             pic16_emitcode("movlw","0x%x",t);
7909             pic16_emitcode("andwf","%s,w",
7910                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7911             pic16_emitcode("movwf","%s",
7912                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7913               
7914             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7915             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7916             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7917           }
7918           continue;
7919         }
7920
7921         if (AOP_TYPE(left) == AOP_ACC) {
7922           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7923           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7924         } else {
7925           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7926           pic16_emitcode("andwf","%s,w",
7927                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7928           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7929           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7930         }
7931         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7932         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7933       }
7934     }
7935   }
7936
7937   release :
7938     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7939   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7940   pic16_freeAsmop(result,NULL,ic,TRUE);     
7941 }
7942
7943 /*-----------------------------------------------------------------*/
7944 /* genOr  - code for or                                            */
7945 /*-----------------------------------------------------------------*/
7946 static void genOr (iCode *ic, iCode *ifx)
7947 {
7948     operand *left, *right, *result;
7949     int size, offset=0;
7950     unsigned long lit = 0L;
7951
7952     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7953
7954     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7955     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7956     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7957
7958     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7959
7960     /* if left is a literal & right is not then exchange them */
7961     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7962         AOP_NEEDSACC(left)) {
7963         operand *tmp = right ;
7964         right = left;
7965         left = tmp;
7966     }
7967
7968     /* if result = right then exchange them */
7969     if(pic16_sameRegs(AOP(result),AOP(right))){
7970         operand *tmp = right ;
7971         right = left;
7972         left = tmp;
7973     }
7974
7975     /* if right is bit then exchange them */
7976     if (AOP_TYPE(right) == AOP_CRY &&
7977         AOP_TYPE(left) != AOP_CRY){
7978         operand *tmp = right ;
7979         right = left;
7980         left = tmp;
7981     }
7982
7983     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7984
7985     if(AOP_TYPE(right) == AOP_LIT)
7986         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7987
7988     size = AOP_SIZE(result);
7989
7990     // if(bit | yy)
7991     // xx = bit | yy;
7992     if (AOP_TYPE(left) == AOP_CRY){
7993         if(AOP_TYPE(right) == AOP_LIT){
7994             // c = bit & literal;
7995             if(lit){
7996                 // lit != 0 => result = 1
7997                 if(AOP_TYPE(result) == AOP_CRY){
7998                   if(size)
7999                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8000                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8001                   //     AOP(result)->aopu.aop_dir,
8002                   //     AOP(result)->aopu.aop_dir);
8003                     else if(ifx)
8004                         continueIfTrue(ifx);
8005                     goto release;
8006                 }
8007             } else {
8008                 // lit == 0 => result = left
8009                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8010                     goto release;
8011                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8012             }
8013         } else {
8014             if (AOP_TYPE(right) == AOP_CRY){
8015               if(pic16_sameRegs(AOP(result),AOP(left))){
8016                 // c = bit | bit;
8017                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8018                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8019                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8020
8021                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8022                          AOP(result)->aopu.aop_dir,
8023                          AOP(result)->aopu.aop_dir);
8024                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8025                          AOP(right)->aopu.aop_dir,
8026                          AOP(right)->aopu.aop_dir);
8027                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8028                          AOP(result)->aopu.aop_dir,
8029                          AOP(result)->aopu.aop_dir);
8030               } else {
8031                 if( AOP_TYPE(result) == AOP_ACC) {
8032                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8033                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8034                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8035                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8036
8037                 } else {
8038
8039                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8040                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8041                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8042                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8043
8044                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8045                                  AOP(result)->aopu.aop_dir,
8046                                  AOP(result)->aopu.aop_dir);
8047                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8048                                  AOP(right)->aopu.aop_dir,
8049                                  AOP(right)->aopu.aop_dir);
8050                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8051                                  AOP(left)->aopu.aop_dir,
8052                                  AOP(left)->aopu.aop_dir);
8053                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8054                                  AOP(result)->aopu.aop_dir,
8055                                  AOP(result)->aopu.aop_dir);
8056                 }
8057               }
8058             } else {
8059                 // c = bit | val;
8060                 symbol *tlbl = newiTempLabel(NULL);
8061                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8062
8063
8064                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8065                 if( AOP_TYPE(right) == AOP_ACC) {
8066                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8067                   emitSKPNZ;
8068                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8069                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8070                 }
8071
8072
8073
8074                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8075                     pic16_emitcode(";XXX setb","c");
8076                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8077                          AOP(left)->aopu.aop_dir,tlbl->key+100);
8078                 pic16_toBoolean(right);
8079                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8080                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8081                     jmpTrueOrFalse(ifx, tlbl);
8082                     goto release;
8083                 } else {
8084                     CLRC;
8085                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8086                 }
8087             }
8088         }
8089         // bit = c
8090         // val = c
8091         if(size)
8092             pic16_outBitC(result);
8093         // if(bit | ...)
8094         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8095             genIfxJump(ifx, "c");           
8096         goto release ;
8097     }
8098
8099     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
8100     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
8101     if((AOP_TYPE(right) == AOP_LIT) &&
8102        (AOP_TYPE(result) == AOP_CRY) &&
8103        (AOP_TYPE(left) != AOP_CRY)){
8104         if(lit){
8105           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8106             // result = 1
8107             if(size)
8108                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8109             else 
8110                 continueIfTrue(ifx);
8111             goto release;
8112         } else {
8113           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8114             // lit = 0, result = boolean(left)
8115             if(size)
8116                 pic16_emitcode(";XXX setb","c");
8117             pic16_toBoolean(right);
8118             if(size){
8119                 symbol *tlbl = newiTempLabel(NULL);
8120                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8121                 CLRC;
8122                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8123             } else {
8124                 genIfxJump (ifx,"a");
8125                 goto release;
8126             }
8127         }
8128         pic16_outBitC(result);
8129         goto release ;
8130     }
8131
8132     /* if left is same as result */
8133     if(pic16_sameRegs(AOP(result),AOP(left))){
8134       int know_W = -1;
8135       for(;size--; offset++,lit>>=8) {
8136         if(AOP_TYPE(right) == AOP_LIT){
8137           if((lit & 0xff) == 0)
8138             /*  or'ing with 0 has no effect */
8139             continue;
8140           else {
8141             int p = pic16_my_powof2(lit & 0xff);
8142             if(p>=0) {
8143               /* only one bit is set in the literal, so use a bsf instruction */
8144               pic16_emitpcode(POC_BSF,
8145                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8146             } else {
8147               if(know_W != (lit & 0xff))
8148                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8149               know_W = lit & 0xff;
8150               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8151             }
8152                     
8153           }
8154         } else {
8155           if (AOP_TYPE(left) == AOP_ACC) {
8156             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
8157             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8158           } else {                  
8159             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8160             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
8161
8162             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8163             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8164
8165           }
8166         }
8167       }
8168     } else {
8169         // left & result in different registers
8170         if(AOP_TYPE(result) == AOP_CRY){
8171             // result = bit
8172             // if(size), result in bit
8173             // if(!size && ifx), conditional oper: if(left | right)
8174             symbol *tlbl = newiTempLabel(NULL);
8175             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8176             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8177
8178
8179             if(size)
8180                 pic16_emitcode(";XXX setb","c");
8181             while(sizer--){
8182                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8183                 pic16_emitcode(";XXX orl","a,%s",
8184                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8185                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8186                 offset++;
8187             }
8188             if(size){
8189                 CLRC;
8190                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8191                 pic16_outBitC(result);
8192             } else if(ifx)
8193                 jmpTrueOrFalse(ifx, tlbl);
8194         } else for(;(size--);offset++){
8195           // normal case
8196           // result = left & right
8197           if(AOP_TYPE(right) == AOP_LIT){
8198             int t = (lit >> (offset*8)) & 0x0FFL;
8199             switch(t) { 
8200             case 0x00:
8201               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8202               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8203
8204               pic16_emitcode("movf","%s,w",
8205                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8206               pic16_emitcode("movwf","%s",
8207                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8208               break;
8209             default:
8210               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
8211               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8212               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8213
8214               pic16_emitcode("movlw","0x%x",t);
8215               pic16_emitcode("iorwf","%s,w",
8216                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8217               pic16_emitcode("movwf","%s",
8218                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8219               
8220             }
8221             continue;
8222           }
8223
8224           // faster than result <- left, anl result,right
8225           // and better if result is SFR
8226           if (AOP_TYPE(left) == AOP_ACC) {
8227             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
8228             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8229           } else {
8230             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8231             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8232
8233             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8234             pic16_emitcode("iorwf","%s,w",
8235                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8236           }
8237           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8238           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8239         }
8240     }
8241
8242 release :
8243     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8244     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8245     pic16_freeAsmop(result,NULL,ic,TRUE);     
8246 }
8247
8248 /*-----------------------------------------------------------------*/
8249 /* genXor - code for xclusive or                                   */
8250 /*-----------------------------------------------------------------*/
8251 static void genXor (iCode *ic, iCode *ifx)
8252 {
8253   operand *left, *right, *result;
8254   int size, offset=0;
8255   unsigned long lit = 0L;
8256
8257   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8258
8259   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8260   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8261   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8262
8263   /* if left is a literal & right is not ||
8264      if left needs acc & right does not */
8265   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8266       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8267     operand *tmp = right ;
8268     right = left;
8269     left = tmp;
8270   }
8271
8272   /* if result = right then exchange them */
8273   if(pic16_sameRegs(AOP(result),AOP(right))){
8274     operand *tmp = right ;
8275     right = left;
8276     left = tmp;
8277   }
8278
8279   /* if right is bit then exchange them */
8280   if (AOP_TYPE(right) == AOP_CRY &&
8281       AOP_TYPE(left) != AOP_CRY){
8282     operand *tmp = right ;
8283     right = left;
8284     left = tmp;
8285   }
8286   if(AOP_TYPE(right) == AOP_LIT)
8287     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8288
8289   size = AOP_SIZE(result);
8290
8291   // if(bit ^ yy)
8292   // xx = bit ^ yy;
8293   if (AOP_TYPE(left) == AOP_CRY){
8294     if(AOP_TYPE(right) == AOP_LIT){
8295       // c = bit & literal;
8296       if(lit>>1){
8297         // lit>>1  != 0 => result = 1
8298         if(AOP_TYPE(result) == AOP_CRY){
8299           if(size)
8300             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8301             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8302           else if(ifx)
8303             continueIfTrue(ifx);
8304           goto release;
8305         }
8306         pic16_emitcode("setb","c");
8307       } else{
8308         // lit == (0 or 1)
8309         if(lit == 0){
8310           // lit == 0, result = left
8311           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8312             goto release;
8313           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8314         } else{
8315           // lit == 1, result = not(left)
8316           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8317             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8318             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8319             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8320             goto release;
8321           } else {
8322             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8323             pic16_emitcode("cpl","c");
8324           }
8325         }
8326       }
8327
8328     } else {
8329       // right != literal
8330       symbol *tlbl = newiTempLabel(NULL);
8331       if (AOP_TYPE(right) == AOP_CRY){
8332         // c = bit ^ bit;
8333         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8334       }
8335       else{
8336         int sizer = AOP_SIZE(right);
8337         // c = bit ^ val
8338         // if val>>1 != 0, result = 1
8339         pic16_emitcode("setb","c");
8340         while(sizer){
8341           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8342           if(sizer == 1)
8343             // test the msb of the lsb
8344             pic16_emitcode("anl","a,#0xfe");
8345           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8346           sizer--;
8347         }
8348         // val = (0,1)
8349         pic16_emitcode("rrc","a");
8350       }
8351       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8352       pic16_emitcode("cpl","c");
8353       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8354     }
8355     // bit = c
8356     // val = c
8357     if(size)
8358       pic16_outBitC(result);
8359     // if(bit | ...)
8360     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8361       genIfxJump(ifx, "c");           
8362     goto release ;
8363   }
8364
8365   if(pic16_sameRegs(AOP(result),AOP(left))){
8366     /* if left is same as result */
8367     for(;size--; offset++) {
8368       if(AOP_TYPE(right) == AOP_LIT){
8369         int t  = (lit >> (offset*8)) & 0x0FFL;
8370         if(t == 0x00L)
8371           continue;
8372         else
8373           if (IS_AOP_PREG(left)) {
8374             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8375             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8376             pic16_aopPut(AOP(result),"a",offset);
8377           } else {
8378             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8379             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8380             pic16_emitcode("xrl","%s,%s",
8381                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8382                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8383           }
8384       } else {
8385         if (AOP_TYPE(left) == AOP_ACC)
8386           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8387         else {
8388           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8389           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8390 /*
8391           if (IS_AOP_PREG(left)) {
8392             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8393             pic16_aopPut(AOP(result),"a",offset);
8394           } else
8395             pic16_emitcode("xrl","%s,a",
8396                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8397 */
8398         }
8399       }
8400     }
8401   } else {
8402     // left & result in different registers
8403     if(AOP_TYPE(result) == AOP_CRY){
8404       // result = bit
8405       // if(size), result in bit
8406       // if(!size && ifx), conditional oper: if(left ^ right)
8407       symbol *tlbl = newiTempLabel(NULL);
8408       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8409       if(size)
8410         pic16_emitcode("setb","c");
8411       while(sizer--){
8412         if((AOP_TYPE(right) == AOP_LIT) &&
8413            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8414           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8415         } else {
8416           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8417           pic16_emitcode("xrl","a,%s",
8418                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8419         }
8420         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8421         offset++;
8422       }
8423       if(size){
8424         CLRC;
8425         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8426         pic16_outBitC(result);
8427       } else if(ifx)
8428         jmpTrueOrFalse(ifx, tlbl);
8429     } else for(;(size--);offset++){
8430       // normal case
8431       // result = left & right
8432       if(AOP_TYPE(right) == AOP_LIT){
8433         int t = (lit >> (offset*8)) & 0x0FFL;
8434         switch(t) { 
8435         case 0x00:
8436           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8437           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8438           pic16_emitcode("movf","%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         case 0xff:
8444           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8445           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8446           pic16_emitcode("comf","%s,w",
8447                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8448           pic16_emitcode("movwf","%s",
8449                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8450           break;
8451         default:
8452           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8453           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8454           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8455           pic16_emitcode("movlw","0x%x",t);
8456           pic16_emitcode("xorwf","%s,w",
8457                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8458           pic16_emitcode("movwf","%s",
8459                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8460
8461         }
8462         continue;
8463       }
8464
8465       // faster than result <- left, anl result,right
8466       // and better if result is SFR
8467       if (AOP_TYPE(left) == AOP_ACC) {
8468         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8469         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8470       } else {
8471         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8472         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8473         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8474         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8475       }
8476       if ( AOP_TYPE(result) != AOP_ACC){
8477         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8478         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8479       }
8480     }
8481   }
8482
8483   release :
8484     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8485   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8486   pic16_freeAsmop(result,NULL,ic,TRUE);     
8487 }
8488
8489 /*-----------------------------------------------------------------*/
8490 /* genInline - write the inline code out                           */
8491 /*-----------------------------------------------------------------*/
8492 static void genInline (iCode *ic)
8493 {
8494   char *buffer, *bp, *bp1;
8495     
8496         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8497
8498         _G.inLine += (!options.asmpeep);
8499
8500         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8501         strcpy(buffer,IC_INLINE(ic));
8502
8503 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
8504
8505         /* emit each line as a code */
8506         while (*bp) {
8507                 if (*bp == '\n') {
8508                         *bp++ = '\0';
8509
8510                         if(*bp1)
8511                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8512                         bp1 = bp;
8513                 } else {
8514                         if (*bp == ':') {
8515                                 bp++;
8516                                 *bp = '\0';
8517                                 bp++;
8518
8519                                 /* print label, use this special format with NULL directive
8520                                  * to denote that the argument should not be indented with tab */
8521                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8522                                 bp1 = bp;
8523                         } else
8524                                 bp++;
8525                 }
8526         }
8527
8528         if ((bp1 != bp) && *bp1)
8529                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8530
8531
8532     Safe_free(buffer);
8533
8534     _G.inLine -= (!options.asmpeep);
8535 }
8536
8537 /*-----------------------------------------------------------------*/
8538 /* genRRC - rotate right with carry                                */
8539 /*-----------------------------------------------------------------*/
8540 static void genRRC (iCode *ic)
8541 {
8542   operand *left , *result ;
8543   int size, offset = 0, same;
8544
8545   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8546
8547   /* rotate right with carry */
8548   left = IC_LEFT(ic);
8549   result=IC_RESULT(ic);
8550   pic16_aopOp (left,ic,FALSE);
8551   pic16_aopOp (result,ic,FALSE);
8552
8553   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8554
8555   same = pic16_sameRegs(AOP(result),AOP(left));
8556
8557   size = AOP_SIZE(result);    
8558
8559   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8560
8561   /* get the lsb and put it into the carry */
8562   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8563
8564   offset = 0 ;
8565
8566   while(size--) {
8567
8568     if(same) {
8569       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8570     } else {
8571       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8572       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8573     }
8574
8575     offset++;
8576   }
8577
8578   pic16_freeAsmop(left,NULL,ic,TRUE);
8579   pic16_freeAsmop(result,NULL,ic,TRUE);
8580 }
8581
8582 /*-----------------------------------------------------------------*/
8583 /* genRLC - generate code for rotate left with carry               */
8584 /*-----------------------------------------------------------------*/
8585 static void genRLC (iCode *ic)
8586 {    
8587   operand *left , *result ;
8588   int size, offset = 0;
8589   int same;
8590
8591   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8592   /* rotate right with carry */
8593   left = IC_LEFT(ic);
8594   result=IC_RESULT(ic);
8595   pic16_aopOp (left,ic,FALSE);
8596   pic16_aopOp (result,ic,FALSE);
8597
8598   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8599
8600   same = pic16_sameRegs(AOP(result),AOP(left));
8601
8602   /* move it to the result */
8603   size = AOP_SIZE(result);    
8604
8605   /* get the msb and put it into the carry */
8606   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8607
8608   offset = 0 ;
8609
8610   while(size--) {
8611
8612     if(same) {
8613       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8614     } else {
8615       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8616       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8617     }
8618
8619     offset++;
8620   }
8621
8622
8623   pic16_freeAsmop(left,NULL,ic,TRUE);
8624   pic16_freeAsmop(result,NULL,ic,TRUE);
8625 }
8626
8627
8628 /* gpasm can get the highest order bit with HIGH/UPPER
8629  * so the following probably is not needed -- VR */
8630  
8631 /*-----------------------------------------------------------------*/
8632 /* genGetHbit - generates code get highest order bit               */
8633 /*-----------------------------------------------------------------*/
8634 static void genGetHbit (iCode *ic)
8635 {
8636     operand *left, *result;
8637     left = IC_LEFT(ic);
8638     result=IC_RESULT(ic);
8639     pic16_aopOp (left,ic,FALSE);
8640     pic16_aopOp (result,ic,FALSE);
8641
8642     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8643     /* get the highest order byte into a */
8644     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8645     if(AOP_TYPE(result) == AOP_CRY){
8646         pic16_emitcode("rlc","a");
8647         pic16_outBitC(result);
8648     }
8649     else{
8650         pic16_emitcode("rl","a");
8651         pic16_emitcode("anl","a,#0x01");
8652         pic16_outAcc(result);
8653     }
8654
8655
8656     pic16_freeAsmop(left,NULL,ic,TRUE);
8657     pic16_freeAsmop(result,NULL,ic,TRUE);
8658 }
8659
8660 #if 0
8661 /*-----------------------------------------------------------------*/
8662 /* AccRol - rotate left accumulator by known count                 */
8663 /*-----------------------------------------------------------------*/
8664 static void AccRol (int shCount)
8665 {
8666     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8667     shCount &= 0x0007;              // shCount : 0..7
8668     switch(shCount){
8669         case 0 :
8670             break;
8671         case 1 :
8672             pic16_emitcode("rl","a");
8673             break;
8674         case 2 :
8675             pic16_emitcode("rl","a");
8676             pic16_emitcode("rl","a");
8677             break;
8678         case 3 :
8679             pic16_emitcode("swap","a");
8680             pic16_emitcode("rr","a");
8681             break;
8682         case 4 :
8683             pic16_emitcode("swap","a");
8684             break;
8685         case 5 :
8686             pic16_emitcode("swap","a");
8687             pic16_emitcode("rl","a");
8688             break;
8689         case 6 :
8690             pic16_emitcode("rr","a");
8691             pic16_emitcode("rr","a");
8692             break;
8693         case 7 :
8694             pic16_emitcode("rr","a");
8695             break;
8696     }
8697 }
8698 #endif
8699
8700 /*-----------------------------------------------------------------*/
8701 /* AccLsh - left shift accumulator by known count                  */
8702 /*-----------------------------------------------------------------*/
8703 static void AccLsh (int shCount)
8704 {
8705         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8706         switch(shCount){
8707                 case 0 :
8708                         return;
8709                         break;
8710                 case 1 :
8711                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8712                         break;
8713                 case 2 :
8714                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8715                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8716                         break;
8717                 case 3 :
8718                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8719                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8720                         break;
8721                 case 4 :
8722                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8723                         break;
8724                 case 5 :
8725                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8726                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8727                         break;
8728                 case 6 :
8729                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8730                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8731                         break;
8732                 case 7 :
8733                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8734                         break;
8735         }
8736
8737         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8738 }
8739
8740 /*-----------------------------------------------------------------*/
8741 /* AccRsh - right shift accumulator by known count                 */
8742 /*-----------------------------------------------------------------*/
8743 static void AccRsh (int shCount, int andmask)
8744 {
8745         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8746         switch(shCount){
8747                 case 0 :
8748                         return; break;
8749                 case 1 :
8750                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8751                         break;
8752                 case 2 :
8753                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8754                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8755                         break;
8756                 case 3 :
8757                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8758                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8759                         break;
8760                 case 4 :
8761                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8762                         break;
8763                 case 5 :
8764                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8765                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8766                         break;
8767                 case 6 :
8768                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8769                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8770                         break;
8771                 case 7 :
8772                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8773                         break;
8774         }
8775         
8776         if(andmask)
8777                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8778         else
8779                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8780 }
8781
8782 #if 0
8783 /*-----------------------------------------------------------------*/
8784 /* AccSRsh - signed right shift accumulator by known count                 */
8785 /*-----------------------------------------------------------------*/
8786 static void AccSRsh (int shCount)
8787 {
8788     symbol *tlbl ;
8789     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8790     if(shCount != 0){
8791         if(shCount == 1){
8792             pic16_emitcode("mov","c,acc.7");
8793             pic16_emitcode("rrc","a");
8794         } else if(shCount == 2){
8795             pic16_emitcode("mov","c,acc.7");
8796             pic16_emitcode("rrc","a");
8797             pic16_emitcode("mov","c,acc.7");
8798             pic16_emitcode("rrc","a");
8799         } else {
8800             tlbl = newiTempLabel(NULL);
8801             /* rotate right accumulator */
8802             AccRol(8 - shCount);
8803             /* and kill the higher order bits */
8804             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8805             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8806             pic16_emitcode("orl","a,#0x%02x",
8807                      (unsigned char)~SRMask[shCount]);
8808             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8809         }
8810     }
8811 }
8812 #endif
8813
8814 /*-----------------------------------------------------------------*/
8815 /* shiftR1Left2Result - shift right one byte from left to result   */
8816 /*-----------------------------------------------------------------*/
8817 static void shiftR1Left2ResultSigned (operand *left, int offl,
8818                                 operand *result, int offr,
8819                                 int shCount)
8820 {
8821   int same;
8822
8823   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8824
8825   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8826
8827   switch(shCount) {
8828   case 1:
8829     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8830     if(same) 
8831       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8832     else {
8833       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8834       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8835     }
8836
8837     break;
8838   case 2:
8839
8840     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8841     if(same) 
8842       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8843     else {
8844       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8845       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8846     }
8847     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8848     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8849
8850     break;
8851
8852   case 3:
8853     if(same)
8854       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8855     else {
8856       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8857       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8858     }
8859
8860     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8861     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8862     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8863
8864     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8865     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8866
8867     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8868     break;
8869
8870   case 4:
8871     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8872     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8873     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8874     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8875     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8876     break;
8877   case 5:
8878     if(same) {
8879       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8880     } else {
8881       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8882       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8883     }
8884     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8885     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8886     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8887     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8888     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8889     break;
8890
8891   case 6:
8892     if(same) {
8893       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8894       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8895       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8896       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8897       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8898       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8899     } else {
8900       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8901       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8902       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8903       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8904       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8905     }
8906     break;
8907
8908   case 7:
8909     if(same) {
8910       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8911       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8912       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8913       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8914     } else {
8915       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8916       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8917       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8918     }
8919
8920   default:
8921     break;
8922   }
8923 }
8924
8925 /*-----------------------------------------------------------------*/
8926 /* shiftR1Left2Result - shift right one byte from left to result   */
8927 /*-----------------------------------------------------------------*/
8928 static void shiftR1Left2Result (operand *left, int offl,
8929                                 operand *result, int offr,
8930                                 int shCount, int sign)
8931 {
8932   int same;
8933
8934   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8935
8936   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8937
8938   /* Copy the msb into the carry if signed. */
8939   if(sign) {
8940     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8941     return;
8942   }
8943
8944
8945
8946   switch(shCount) {
8947   case 1:
8948     emitCLRC;
8949     if(same) 
8950       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8951     else {
8952       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8953       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8954     }
8955     break;
8956   case 2:
8957     emitCLRC;
8958     if(same) {
8959       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8960     } else {
8961       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8962       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8963     }
8964     emitCLRC;
8965     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8966
8967     break;
8968   case 3:
8969     if(same)
8970       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8971     else {
8972       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8973       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8974     }
8975
8976     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8977     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8978     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8979     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8980     break;
8981       
8982   case 4:
8983     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8984     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8985     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8986     break;
8987
8988   case 5:
8989     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8990     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8991     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8992     //emitCLRC;
8993     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8994
8995     break;
8996   case 6:
8997
8998     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8999     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9000     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9001     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
9002     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
9003     break;
9004
9005   case 7:
9006
9007     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9008     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9009     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9010
9011     break;
9012
9013   default:
9014     break;
9015   }
9016 }
9017
9018 /*-----------------------------------------------------------------*/
9019 /* shiftL1Left2Result - shift left one byte from left to result    */
9020 /*-----------------------------------------------------------------*/
9021 static void shiftL1Left2Result (operand *left, int offl,
9022                                 operand *result, int offr, int shCount)
9023 {
9024   int same;
9025
9026   //    char *l;
9027   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9028
9029   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9030   DEBUGpic16_emitcode ("; ***","same =  %d",same);
9031     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9032     //    MOVA(l);
9033     /* shift left accumulator */
9034     //AccLsh(shCount); // don't comment out just yet...
9035   //    pic16_aopPut(AOP(result),"a",offr);
9036
9037   switch(shCount) {
9038   case 1:
9039     /* Shift left 1 bit position */
9040     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9041     if(same) {
9042       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9043     } else {
9044       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9045       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9046     }
9047     break;
9048   case 2:
9049     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9050     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9051     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9052     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9053     break;
9054   case 3:
9055     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9056     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9057     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9058     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9059     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9060     break;
9061   case 4:
9062     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9063     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9064     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9065     break;
9066   case 5:
9067     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9068     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9069     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9070     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9071     break;
9072   case 6:
9073     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9074     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9075     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9076     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9077     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9078     break;
9079   case 7:
9080     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9081     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9082     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9083     break;
9084
9085   default:
9086     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9087   }
9088
9089 }
9090
9091 /*-----------------------------------------------------------------*/
9092 /* movLeft2Result - move byte from left to result                  */
9093 /*-----------------------------------------------------------------*/
9094 static void movLeft2Result (operand *left, int offl,
9095                             operand *result, int offr)
9096 {
9097   char *l;
9098   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9099   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9100     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9101
9102     if (*l == '@' && (IS_AOP_PREG(result))) {
9103       pic16_emitcode("mov","a,%s",l);
9104       pic16_aopPut(AOP(result),"a",offr);
9105     } else {
9106       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9107       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9108     }
9109   }
9110 }
9111
9112 /*-----------------------------------------------------------------*/
9113 /* shiftL2Left2Result - shift left two bytes from left to result   */
9114 /*-----------------------------------------------------------------*/
9115 static void shiftL2Left2Result (operand *left, int offl,
9116                                 operand *result, int offr, int shCount)
9117 {
9118   int same = pic16_sameRegs(AOP(result), AOP(left));
9119   int i;
9120
9121   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9122
9123   if (same && (offl != offr)) { // shift bytes
9124     if (offr > offl) {
9125        for(i=1;i>-1;i--) {
9126          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9127          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9128        }
9129     } else { // just treat as different later on
9130                 same = 0;
9131     }
9132   }
9133
9134   if(same) {
9135     switch(shCount) {
9136     case 0:
9137       break;
9138     case 1:
9139     case 2:
9140     case 3:
9141
9142       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9143       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9144       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9145
9146       while(--shCount) {
9147                 emitCLRC;
9148                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9149                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9150       }
9151
9152       break;
9153     case 4:
9154     case 5:
9155       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9156       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9157       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9158       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9159       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9160       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9161       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9162       if(shCount >=5) {
9163                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9164                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9165       }
9166       break;
9167     case 6:
9168       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9169       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9170       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9171       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9172       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9173       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9174       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9175       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9176       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9177       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9178       break;
9179     case 7:
9180       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9181       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9182       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9183       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9184       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9185     }
9186
9187   } else {
9188     switch(shCount) {
9189     case 0:
9190       break;
9191     case 1:
9192     case 2:
9193     case 3:
9194       /* note, use a mov/add for the shift since the mov has a
9195          chance of getting optimized out */
9196       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9197       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9198       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9199       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9200       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9201
9202       while(--shCount) {
9203                 emitCLRC;
9204                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9205                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9206       }
9207       break;
9208
9209     case 4:
9210     case 5:
9211       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9212       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9213       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9214       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9215       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9216       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9217       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9218       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9219
9220
9221       if(shCount == 5) {
9222                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9223                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9224       }
9225       break;
9226     case 6:
9227       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9228       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9229       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9230       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9231
9232       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9233       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9234       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9235       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9236       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9237       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9238       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9239       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9240       break;
9241     case 7:
9242       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9243       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9244       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9245       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9246       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9247     }
9248   }
9249
9250 }
9251 /*-----------------------------------------------------------------*/
9252 /* shiftR2Left2Result - shift right two bytes from left to result  */
9253 /*-----------------------------------------------------------------*/
9254 static void shiftR2Left2Result (operand *left, int offl,
9255                                 operand *result, int offr,
9256                                 int shCount, int sign)
9257 {
9258   int same = pic16_sameRegs(AOP(result), AOP(left));
9259   int i;
9260   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9261
9262   if (same && (offl != offr)) { // shift right bytes
9263     if (offr < offl) {
9264        for(i=0;i<2;i++) {
9265          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9266          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9267        }
9268     } else { // just treat as different later on
9269                 same = 0;
9270     }
9271   }
9272
9273   switch(shCount) {
9274   case 0:
9275     break;
9276   case 1:
9277   case 2:
9278   case 3:
9279     if(sign)
9280       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9281     else
9282       emitCLRC;
9283
9284     if(same) {
9285       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9286       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9287     } else {
9288       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9289       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9290       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9291       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9292     }
9293
9294     while(--shCount) {
9295       if(sign)
9296                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9297       else
9298                 emitCLRC;
9299       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9300       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9301     }
9302     break;
9303   case 4:
9304   case 5:
9305     if(same) {
9306
9307       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9308       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9309       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9310
9311       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9312       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9313       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9314       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9315     } else {
9316       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9317       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9318       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9319
9320       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9321       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9322       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9323       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9324       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9325     }
9326
9327     if(shCount >=5) {
9328       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9329       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9330     }
9331
9332     if(sign) {
9333       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9334       pic16_emitpcode(POC_BTFSC, 
9335                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9336       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9337     }
9338
9339     break;
9340
9341   case 6:
9342     if(same) {
9343
9344       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9345       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9346
9347       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9348       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9349       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9350       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9351       if(sign) {
9352         pic16_emitpcode(POC_BTFSC, 
9353                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9354         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9355       }
9356       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9357       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9358       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9359       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9360     } else {
9361       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9362       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9363       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9364       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9365       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9366       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9367       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9368       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9369       if(sign) {
9370         pic16_emitpcode(POC_BTFSC, 
9371                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9372         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9373       }
9374       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9375       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9376
9377         
9378     }
9379
9380     break;
9381   case 7:
9382     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9383     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9384     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9385     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9386     if(sign) {
9387       emitSKPNC;
9388       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9389     } else 
9390       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9391   }
9392 }
9393
9394
9395 /*-----------------------------------------------------------------*/
9396 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9397 /*-----------------------------------------------------------------*/
9398 static void shiftLLeftOrResult (operand *left, int offl,
9399                                 operand *result, int offr, int shCount)
9400 {
9401     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9402
9403     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9404     /* shift left accumulator */
9405     AccLsh(shCount);
9406     /* or with result */
9407     /* back to result */
9408     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9409 }
9410
9411 /*-----------------------------------------------------------------*/
9412 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9413 /*-----------------------------------------------------------------*/
9414 static void shiftRLeftOrResult (operand *left, int offl,
9415                                 operand *result, int offr, int shCount)
9416 {
9417     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9418     
9419     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9420     /* shift right accumulator */
9421     AccRsh(shCount, 1);
9422     /* or with result */
9423     /* back to result */
9424     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9425 }
9426
9427 /*-----------------------------------------------------------------*/
9428 /* genlshOne - left shift a one byte quantity by known count       */
9429 /*-----------------------------------------------------------------*/
9430 static void genlshOne (operand *result, operand *left, int shCount)
9431 {       
9432     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9433     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9434 }
9435
9436 /*-----------------------------------------------------------------*/
9437 /* genlshTwo - left shift two bytes by known amount != 0           */
9438 /*-----------------------------------------------------------------*/
9439 static void genlshTwo (operand *result,operand *left, int shCount)
9440 {
9441     int size;
9442     
9443     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9444     size = pic16_getDataSize(result);
9445
9446     /* if shCount >= 8 */
9447     if (shCount >= 8) {
9448         shCount -= 8 ;
9449
9450         if (size > 1){
9451             if (shCount)
9452                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9453             else 
9454                 movLeft2Result(left, LSB, result, MSB16);
9455         }
9456         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9457     }
9458
9459     /*  1 <= shCount <= 7 */
9460     else {  
9461         if(size == 1)
9462             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9463         else 
9464             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9465     }
9466 }
9467
9468 /*-----------------------------------------------------------------*/
9469 /* shiftLLong - shift left one long from left to result            */
9470 /* offr = LSB or MSB16                                             */
9471 /*-----------------------------------------------------------------*/
9472 static void shiftLLong (operand *left, operand *result, int offr )
9473 {
9474     int size = AOP_SIZE(result);
9475     int same = pic16_sameRegs(AOP(left),AOP(result));
9476         int i;
9477
9478     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9479
9480         if (same && (offr == MSB16)) { //shift one byte
9481                 for(i=size-1;i>=MSB16;i--) {
9482                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9483                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9484                 }
9485         } else {
9486                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9487         }
9488         
9489     if (size > LSB+offr ){
9490                 if (same) {
9491                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9492                 } else {
9493                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9494                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9495                 }
9496          }
9497
9498     if(size > MSB16+offr){
9499                 if (same) {
9500                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9501                 } else {
9502                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9503                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9504                 }
9505     }
9506
9507     if(size > MSB24+offr){
9508                 if (same) {
9509                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9510                 } else {
9511                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9512                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9513                 }
9514     }
9515
9516     if(size > MSB32+offr){
9517                 if (same) {
9518                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9519                 } else {
9520                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9521                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9522                 }
9523     }
9524     if(offr != LSB)
9525                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9526
9527 }
9528
9529 /*-----------------------------------------------------------------*/
9530 /* genlshFour - shift four byte by a known amount != 0             */
9531 /*-----------------------------------------------------------------*/
9532 static void genlshFour (operand *result, operand *left, int shCount)
9533 {
9534     int size;
9535
9536     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9537     size = AOP_SIZE(result);
9538
9539     /* if shifting more that 3 bytes */
9540     if (shCount >= 24 ) {
9541         shCount -= 24;
9542         if (shCount)
9543             /* lowest order of left goes to the highest
9544             order of the destination */
9545             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9546         else
9547             movLeft2Result(left, LSB, result, MSB32);
9548
9549                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9550                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9551                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9552
9553         return;
9554     }
9555
9556     /* more than two bytes */
9557     else if ( shCount >= 16 ) {
9558         /* lower order two bytes goes to higher order two bytes */
9559         shCount -= 16;
9560         /* if some more remaining */
9561         if (shCount)
9562             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9563         else {
9564             movLeft2Result(left, MSB16, result, MSB32);
9565             movLeft2Result(left, LSB, result, MSB24);
9566         }
9567                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9568                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9569         return;
9570     }    
9571
9572     /* if more than 1 byte */
9573     else if ( shCount >= 8 ) {
9574         /* lower order three bytes goes to higher order  three bytes */
9575         shCount -= 8;
9576         if(size == 2){
9577             if(shCount)
9578                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9579             else
9580                 movLeft2Result(left, LSB, result, MSB16);
9581         }
9582         else{   /* size = 4 */
9583             if(shCount == 0){
9584                 movLeft2Result(left, MSB24, result, MSB32);
9585                 movLeft2Result(left, MSB16, result, MSB24);
9586                 movLeft2Result(left, LSB, result, MSB16);
9587                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9588             }
9589             else if(shCount == 1)
9590                 shiftLLong(left, result, MSB16);
9591             else{
9592                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9593                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9594                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9595                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9596             }
9597         }
9598     }
9599
9600     /* 1 <= shCount <= 7 */
9601     else if(shCount <= 3)
9602     { 
9603         shiftLLong(left, result, LSB);
9604         while(--shCount >= 1)
9605             shiftLLong(result, result, LSB);
9606     }
9607     /* 3 <= shCount <= 7, optimize */
9608     else{
9609         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9610         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9611         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9612     }
9613 }
9614
9615 /*-----------------------------------------------------------------*/
9616 /* genLeftShiftLiteral - left shifting by known count              */
9617 /*-----------------------------------------------------------------*/
9618 void pic16_genLeftShiftLiteral (operand *left,
9619                                  operand *right,
9620                                  operand *result,
9621                                  iCode *ic)
9622 {    
9623     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9624     int size;
9625
9626     FENTRY;
9627     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9628     pic16_freeAsmop(right,NULL,ic,TRUE);
9629
9630     pic16_aopOp(left,ic,FALSE);
9631     pic16_aopOp(result,ic,FALSE);
9632
9633     size = getSize(operandType(result));
9634
9635 #if VIEW_SIZE
9636     pic16_emitcode("; shift left ","result %d, left %d",size,
9637              AOP_SIZE(left));
9638 #endif
9639
9640     /* I suppose that the left size >= result size */
9641     if(shCount == 0){
9642         while(size--){
9643             movLeft2Result(left, size, result, size);
9644         }
9645     }
9646
9647     else if(shCount >= (size * 8))
9648         while(size--)
9649             pic16_aopPut(AOP(result),zero,size);
9650     else{
9651         switch (size) {
9652             case 1:
9653                 genlshOne (result,left,shCount);
9654                 break;
9655
9656             case 2:
9657             case 3:
9658                 genlshTwo (result,left,shCount);
9659                 break;
9660
9661             case 4:
9662                 genlshFour (result,left,shCount);
9663                 break;
9664         }
9665     }
9666     pic16_freeAsmop(left,NULL,ic,TRUE);
9667     pic16_freeAsmop(result,NULL,ic,TRUE);
9668 }
9669
9670 /*-----------------------------------------------------------------*
9671  * genMultiAsm - repeat assembly instruction for size of register.
9672  * if endian == 1, then the high byte (i.e base address + size of 
9673  * register) is used first else the low byte is used first;
9674  *-----------------------------------------------------------------*/
9675 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9676 {
9677
9678   int offset = 0;
9679
9680   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9681
9682   if(!reg)
9683     return;
9684
9685   if(!endian) {
9686     endian = 1;
9687   } else {
9688     endian = -1;
9689     offset = size-1;
9690   }
9691
9692   while(size--) {
9693     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9694     offset += endian;
9695   }
9696
9697 }
9698
9699 #if !(USE_GENERIC_SIGNED_SHIFT)
9700 /*-----------------------------------------------------------------*/
9701 /* genLeftShift - generates code for left shifting                 */
9702 /*-----------------------------------------------------------------*/
9703 static void genLeftShift (iCode *ic)
9704 {
9705   operand *left,*right, *result;
9706   int size, offset;
9707 //  char *l;
9708   symbol *tlbl , *tlbl1;
9709   pCodeOp *pctemp;
9710
9711   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9712
9713   right = IC_RIGHT(ic);
9714   left  = IC_LEFT(ic);
9715   result = IC_RESULT(ic);
9716
9717   pic16_aopOp(right,ic,FALSE);
9718
9719   /* if the shift count is known then do it 
9720      as efficiently as possible */
9721   if (AOP_TYPE(right) == AOP_LIT) {
9722     pic16_genLeftShiftLiteral (left,right,result,ic);
9723     return ;
9724   }
9725
9726   /* shift count is unknown then we have to form
9727    * a loop. Get the loop count in WREG : Note: we take
9728    * only the lower order byte since shifting
9729    * more than 32 bits make no sense anyway, ( the
9730    * largest size of an object can be only 32 bits ) */
9731   
9732   pic16_aopOp(left,ic,FALSE);
9733   pic16_aopOp(result,ic,FALSE);
9734
9735   /* now move the left to the result if they are not the
9736    * same, and if size > 1,
9737    * and if right is not same to result (!!!) -- VR */
9738   if (!pic16_sameRegs(AOP(left),AOP(result))
9739       && (AOP_SIZE(result) > 1)) {
9740
9741     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9742
9743     size = AOP_SIZE(result);
9744     offset=0;
9745     while (size--) {
9746
9747 #if 0
9748       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9749       if (*l == '@' && (IS_AOP_PREG(result))) {
9750
9751           pic16_emitcode("mov","a,%s",l);
9752           pic16_aopPut(AOP(result),"a",offset);
9753       } else
9754 #endif
9755       {
9756         /* we don't know if left is a literal or a register, take care -- VR */
9757         mov2f(AOP(result), AOP(left), offset);
9758       }
9759       offset++;
9760     }
9761   }
9762
9763   size = AOP_SIZE(result);
9764
9765   /* if it is only one byte then */
9766   if (size == 1) {
9767     if(optimized_for_speed) {
9768       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9769       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9770       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9771       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9772       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9773       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9774       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9775       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9776       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9777       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9778       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9779       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9780     } else {
9781
9782       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9783
9784       tlbl = newiTempLabel(NULL);
9785
9786 #if 1
9787       /* this is already done, why change it? */
9788       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9789                 mov2f(AOP(result), AOP(left), 0);
9790       }
9791 #endif
9792
9793       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9794       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9795       pic16_emitpLabel(tlbl->key);
9796       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9797       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9798       emitSKPC;
9799       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9800     }
9801     goto release ;
9802   }
9803     
9804   if (pic16_sameRegs(AOP(left),AOP(result))) {
9805
9806     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9807     
9808     tlbl = newiTempLabel(NULL);
9809     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9810     genMultiAsm(POC_RRCF, result, size,1);
9811     pic16_emitpLabel(tlbl->key);
9812     genMultiAsm(POC_RLCF, result, size,0);
9813     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9814     emitSKPC;
9815     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9816     goto release;
9817   }
9818
9819   //tlbl = newiTempLabel(NULL);
9820   //offset = 0 ;   
9821   //tlbl1 = newiTempLabel(NULL);
9822
9823   //reAdjustPreg(AOP(result));    
9824     
9825   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9826   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9827   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9828   //MOVA(l);
9829   //pic16_emitcode("add","a,acc");         
9830   //pic16_aopPut(AOP(result),"a",offset++);
9831   //while (--size) {
9832   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9833   //  MOVA(l);
9834   //  pic16_emitcode("rlc","a");         
9835   //  pic16_aopPut(AOP(result),"a",offset++);
9836   //}
9837   //reAdjustPreg(AOP(result));
9838
9839   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9840   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9841
9842
9843   tlbl = newiTempLabel(NULL);
9844   tlbl1= newiTempLabel(NULL);
9845
9846   size = AOP_SIZE(result);
9847   offset = 1;
9848
9849   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9850
9851   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9852
9853   /* offset should be 0, 1 or 3 */
9854   
9855   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9856   emitSKPNZ;
9857   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9858
9859   pic16_emitpcode(POC_MOVWF, pctemp);
9860
9861
9862   pic16_emitpLabel(tlbl->key);
9863
9864   emitCLRC;
9865   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9866   while(--size)
9867     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9868
9869   pic16_emitpcode(POC_DECFSZ,  pctemp);
9870   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9871   pic16_emitpLabel(tlbl1->key);
9872
9873   pic16_popReleaseTempReg(pctemp,1);
9874
9875
9876  release:
9877   pic16_freeAsmop (right,NULL,ic,TRUE);
9878   pic16_freeAsmop(left,NULL,ic,TRUE);
9879   pic16_freeAsmop(result,NULL,ic,TRUE);
9880 }
9881 #endif
9882
9883
9884 #if 0
9885 #error old code (left here for reference)
9886 /*-----------------------------------------------------------------*/
9887 /* genLeftShift - generates code for left shifting                 */
9888 /*-----------------------------------------------------------------*/
9889 static void genLeftShift (iCode *ic)
9890 {
9891   operand *left,*right, *result;
9892   int size, offset;
9893   char *l;
9894   symbol *tlbl , *tlbl1;
9895   pCodeOp *pctemp;
9896
9897   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9898
9899   right = IC_RIGHT(ic);
9900   left  = IC_LEFT(ic);
9901   result = IC_RESULT(ic);
9902
9903   pic16_aopOp(right,ic,FALSE);
9904
9905   /* if the shift count is known then do it 
9906      as efficiently as possible */
9907   if (AOP_TYPE(right) == AOP_LIT) {
9908     pic16_genLeftShiftLiteral (left,right,result,ic);
9909     return ;
9910   }
9911
9912   /* shift count is unknown then we have to form 
9913      a loop get the loop count in B : Note: we take
9914      only the lower order byte since shifting
9915      more that 32 bits make no sense anyway, ( the
9916      largest size of an object can be only 32 bits ) */  
9917
9918     
9919   pic16_aopOp(left,ic,FALSE);
9920   pic16_aopOp(result,ic,FALSE);
9921
9922   /* now move the left to the result if they are not the
9923      same */
9924   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9925       AOP_SIZE(result) > 1) {
9926
9927     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9928
9929     size = AOP_SIZE(result);
9930     offset=0;
9931     while (size--) {
9932       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9933       if (*l == '@' && (IS_AOP_PREG(result))) {
9934
9935         pic16_emitcode("mov","a,%s",l);
9936         pic16_aopPut(AOP(result),"a",offset);
9937       } else {
9938
9939         /* we don't know if left is a literal or a register, take care -- VR */
9940         mov2f(AOP(result), AOP(left), offset);
9941       }
9942       offset++;
9943     }
9944   }
9945
9946   size = AOP_SIZE(result);
9947
9948   /* if it is only one byte then */
9949   if (size == 1) {
9950     if(optimized_for_speed) {
9951       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9952       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9953       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9954       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9955       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9956       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9957       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9958       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9959       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9960       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9961       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9962       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9963     } else {
9964
9965       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9966
9967       tlbl = newiTempLabel(NULL);
9968       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9969                 mov2f(AOP(result), AOP(left), 0);
9970                 
9971 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9972 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9973       }
9974
9975       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9976       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9977       pic16_emitpLabel(tlbl->key);
9978       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9979       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9980       emitSKPC;
9981       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9982     }
9983     goto release ;
9984   }
9985     
9986   if (pic16_sameRegs(AOP(left),AOP(result))) {
9987
9988     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9989     
9990     tlbl = newiTempLabel(NULL);
9991     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9992     genMultiAsm(POC_RRCF, result, size,1);
9993     pic16_emitpLabel(tlbl->key);
9994     genMultiAsm(POC_RLCF, result, size,0);
9995     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9996     emitSKPC;
9997     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9998     goto release;
9999   }
10000
10001   //tlbl = newiTempLabel(NULL);
10002   //offset = 0 ;   
10003   //tlbl1 = newiTempLabel(NULL);
10004
10005   //reAdjustPreg(AOP(result));    
10006     
10007   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
10008   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10009   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10010   //MOVA(l);
10011   //pic16_emitcode("add","a,acc");         
10012   //pic16_aopPut(AOP(result),"a",offset++);
10013   //while (--size) {
10014   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10015   //  MOVA(l);
10016   //  pic16_emitcode("rlc","a");         
10017   //  pic16_aopPut(AOP(result),"a",offset++);
10018   //}
10019   //reAdjustPreg(AOP(result));
10020
10021   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10022   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10023
10024
10025   tlbl = newiTempLabel(NULL);
10026   tlbl1= newiTempLabel(NULL);
10027
10028   size = AOP_SIZE(result);
10029   offset = 1;
10030
10031   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10032
10033   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10034
10035   /* offset should be 0, 1 or 3 */
10036   
10037   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10038   emitSKPNZ;
10039   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10040
10041   pic16_emitpcode(POC_MOVWF, pctemp);
10042
10043
10044   pic16_emitpLabel(tlbl->key);
10045
10046   emitCLRC;
10047   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
10048   while(--size)
10049     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10050
10051   pic16_emitpcode(POC_DECFSZ,  pctemp);
10052   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10053   pic16_emitpLabel(tlbl1->key);
10054
10055   pic16_popReleaseTempReg(pctemp,1);
10056
10057
10058  release:
10059   pic16_freeAsmop (right,NULL,ic,TRUE);
10060   pic16_freeAsmop(left,NULL,ic,TRUE);
10061   pic16_freeAsmop(result,NULL,ic,TRUE);
10062 }
10063 #endif
10064
10065 /*-----------------------------------------------------------------*/
10066 /* genrshOne - right shift a one byte quantity by known count      */
10067 /*-----------------------------------------------------------------*/
10068 static void genrshOne (operand *result, operand *left,
10069                        int shCount, int sign)
10070 {
10071     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10072     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10073 }
10074
10075 /*-----------------------------------------------------------------*/
10076 /* genrshTwo - right shift two bytes by known amount != 0          */
10077 /*-----------------------------------------------------------------*/
10078 static void genrshTwo (operand *result,operand *left,
10079                        int shCount, int sign)
10080 {
10081   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10082   /* if shCount >= 8 */
10083   if (shCount >= 8) {
10084     shCount -= 8 ;
10085     if (shCount)
10086       shiftR1Left2Result(left, MSB16, result, LSB,
10087                          shCount, sign);
10088     else
10089       movLeft2Result(left, MSB16, result, LSB);
10090
10091     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
10092
10093     if(sign) {
10094       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10095       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
10096     }
10097   }
10098
10099   /*  1 <= shCount <= 7 */
10100   else
10101     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
10102 }
10103
10104 /*-----------------------------------------------------------------*/
10105 /* shiftRLong - shift right one long from left to result           */
10106 /* offl = LSB or MSB16                                             */
10107 /*-----------------------------------------------------------------*/
10108 static void shiftRLong (operand *left, int offl,
10109                         operand *result, int sign)
10110 {
10111     int size = AOP_SIZE(result);
10112     int same = pic16_sameRegs(AOP(left),AOP(result));
10113     int i;
10114     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10115
10116         if (same && (offl == MSB16)) { //shift one byte right
10117                 for(i=MSB16;i<size;i++) {
10118                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10119                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10120                 }
10121         }
10122
10123     if(sign)
10124                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10125         else
10126                 emitCLRC;
10127
10128         if (same) {
10129                 if (offl == LSB)
10130                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10131         } else {
10132         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10133         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10134         }
10135
10136     if(offl == MSB16) {
10137         /* add sign of "a" */
10138         pic16_addSign(result, MSB32, sign);
10139         }
10140
10141         if (same) {
10142         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10143         } else {
10144         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10145         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10146         }
10147         
10148         if (same) {
10149         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10150         } else {
10151         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10152         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10153         }
10154
10155         if (same) {
10156         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10157         } else {
10158         if(offl == LSB){
10159                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10160                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10161         }
10162         }
10163 }
10164
10165 /*-----------------------------------------------------------------*/
10166 /* genrshFour - shift four byte by a known amount != 0             */
10167 /*-----------------------------------------------------------------*/
10168 static void genrshFour (operand *result, operand *left,
10169                         int shCount, int sign)
10170 {
10171   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10172   /* if shifting more that 3 bytes */
10173   if(shCount >= 24 ) {
10174     shCount -= 24;
10175     if(shCount)
10176       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10177     else
10178       movLeft2Result(left, MSB32, result, LSB);
10179
10180     pic16_addSign(result, MSB16, sign);
10181   }
10182   else if(shCount >= 16){
10183     shCount -= 16;
10184     if(shCount)
10185       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10186     else{
10187       movLeft2Result(left, MSB24, result, LSB);
10188       movLeft2Result(left, MSB32, result, MSB16);
10189     }
10190     pic16_addSign(result, MSB24, sign);
10191   }
10192   else if(shCount >= 8){
10193     shCount -= 8;
10194     if(shCount == 1)
10195       shiftRLong(left, MSB16, result, sign);
10196     else if(shCount == 0){
10197       movLeft2Result(left, MSB16, result, LSB);
10198       movLeft2Result(left, MSB24, result, MSB16);
10199       movLeft2Result(left, MSB32, result, MSB24);
10200       pic16_addSign(result, MSB32, sign);
10201     }
10202     else{ //shcount >= 2
10203       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10204       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10205       /* the last shift is signed */
10206       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10207       pic16_addSign(result, MSB32, sign);
10208     }
10209   }
10210   else{   /* 1 <= shCount <= 7 */
10211     if(shCount <= 2){
10212       shiftRLong(left, LSB, result, sign);
10213       if(shCount == 2)
10214         shiftRLong(result, LSB, result, sign);
10215     }
10216     else{
10217       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10218       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10219       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10220     }
10221   }
10222 }
10223
10224 /*-----------------------------------------------------------------*/
10225 /* genRightShiftLiteral - right shifting by known count            */
10226 /*-----------------------------------------------------------------*/
10227 static void genRightShiftLiteral (operand *left,
10228                                   operand *right,
10229                                   operand *result,
10230                                   iCode *ic,
10231                                   int sign)
10232 {    
10233   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10234   int lsize,res_size;
10235
10236   pic16_freeAsmop(right,NULL,ic,TRUE);
10237
10238   pic16_aopOp(left,ic,FALSE);
10239   pic16_aopOp(result,ic,FALSE);
10240
10241   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10242
10243 #if VIEW_SIZE
10244   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10245                  AOP_SIZE(left));
10246 #endif
10247
10248   lsize = pic16_getDataSize(left);
10249   res_size = pic16_getDataSize(result);
10250   /* test the LEFT size !!! */
10251
10252   /* I suppose that the left size >= result size */
10253   if(shCount == 0){
10254     while(res_size--)
10255       movLeft2Result(left, lsize, result, res_size);
10256   }
10257
10258   else if(shCount >= (lsize * 8)){
10259
10260     if(res_size == 1) {
10261       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10262       if(sign) {
10263         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10264         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10265       }
10266     } else {
10267
10268       if(sign) {
10269         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10270         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10271         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10272         while(res_size--)
10273           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10274
10275       } else {
10276
10277         while(res_size--)
10278           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10279       }
10280     }
10281   } else {
10282
10283     switch (res_size) {
10284     case 1:
10285       genrshOne (result,left,shCount,sign);
10286       break;
10287
10288     case 2:
10289       genrshTwo (result,left,shCount,sign);
10290       break;
10291
10292     case 4:
10293       genrshFour (result,left,shCount,sign);
10294       break;
10295     default :
10296       break;
10297     }
10298
10299   }
10300
10301   pic16_freeAsmop(left,NULL,ic,TRUE);
10302   pic16_freeAsmop(result,NULL,ic,TRUE);
10303 }
10304
10305 #if !(USE_GENERIC_SIGNED_SHIFT)
10306 /*-----------------------------------------------------------------*/
10307 /* genSignedRightShift - right shift of signed number              */
10308 /*-----------------------------------------------------------------*/
10309 static void genSignedRightShift (iCode *ic)
10310 {
10311   operand *right, *left, *result;
10312   int size, offset;
10313   //  char *l;
10314   symbol *tlbl, *tlbl1 ;
10315   pCodeOp *pctemp;
10316
10317   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10318
10319   /* we do it the hard way put the shift count in b
10320      and loop thru preserving the sign */
10321   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10322
10323   right = IC_RIGHT(ic);
10324   left  = IC_LEFT(ic);
10325   result = IC_RESULT(ic);
10326
10327   pic16_aopOp(right,ic,FALSE);  
10328   pic16_aopOp(left,ic,FALSE);
10329   pic16_aopOp(result,ic,FALSE);
10330
10331
10332   if ( AOP_TYPE(right) == AOP_LIT) {
10333     genRightShiftLiteral (left,right,result,ic,1);
10334     return ;
10335   }
10336   /* shift count is unknown then we have to form 
10337      a loop get the loop count in B : Note: we take
10338      only the lower order byte since shifting
10339      more that 32 bits make no sense anyway, ( the
10340      largest size of an object can be only 32 bits ) */  
10341
10342   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10343   //pic16_emitcode("inc","b");
10344   //pic16_freeAsmop (right,NULL,ic,TRUE);
10345   //pic16_aopOp(left,ic,FALSE);
10346   //pic16_aopOp(result,ic,FALSE);
10347
10348   /* now move the left to the result if they are not the
10349      same */
10350   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10351       AOP_SIZE(result) > 1) {
10352
10353     size = AOP_SIZE(result);
10354     offset=0;
10355     while (size--) { 
10356       /*
10357         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10358         if (*l == '@' && IS_AOP_PREG(result)) {
10359
10360         pic16_emitcode("mov","a,%s",l);
10361         pic16_aopPut(AOP(result),"a",offset);
10362         } else
10363         pic16_aopPut(AOP(result),l,offset);
10364       */
10365       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10366       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10367
10368       offset++;
10369     }
10370   }
10371
10372   /* mov the highest order bit to OVR */    
10373   tlbl = newiTempLabel(NULL);
10374   tlbl1= newiTempLabel(NULL);
10375
10376   size = AOP_SIZE(result);
10377   offset = size - 1;
10378
10379   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10380
10381   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10382
10383   /* offset should be 0, 1 or 3 */
10384   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10385   emitSKPNZ;
10386   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10387
10388   pic16_emitpcode(POC_MOVWF, pctemp);
10389
10390
10391   pic16_emitpLabel(tlbl->key);
10392
10393   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10394   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10395
10396   while(--size) {
10397     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10398   }
10399
10400   pic16_emitpcode(POC_DECFSZ,  pctemp);
10401   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10402   pic16_emitpLabel(tlbl1->key);
10403
10404   pic16_popReleaseTempReg(pctemp,1);
10405 #if 0
10406   size = AOP_SIZE(result);
10407   offset = size - 1;
10408   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10409   pic16_emitcode("rlc","a");
10410   pic16_emitcode("mov","ov,c");
10411   /* if it is only one byte then */
10412   if (size == 1) {
10413     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10414     MOVA(l);
10415     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10416     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10417     pic16_emitcode("mov","c,ov");
10418     pic16_emitcode("rrc","a");
10419     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10420     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10421     pic16_aopPut(AOP(result),"a",0);
10422     goto release ;
10423   }
10424
10425   reAdjustPreg(AOP(result));
10426   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10427   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10428   pic16_emitcode("mov","c,ov");
10429   while (size--) {
10430     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10431     MOVA(l);
10432     pic16_emitcode("rrc","a");         
10433     pic16_aopPut(AOP(result),"a",offset--);
10434   }
10435   reAdjustPreg(AOP(result));
10436   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10437   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10438
10439  release:
10440 #endif
10441
10442   pic16_freeAsmop(left,NULL,ic,TRUE);
10443   pic16_freeAsmop(result,NULL,ic,TRUE);
10444   pic16_freeAsmop(right,NULL,ic,TRUE);
10445 }
10446 #endif
10447
10448 #if !(USE_GENERIC_SIGNED_SHIFT)
10449 #warning This implementation of genRightShift() is incomplete!
10450 /*-----------------------------------------------------------------*/
10451 /* genRightShift - generate code for right shifting                */
10452 /*-----------------------------------------------------------------*/
10453 static void genRightShift (iCode *ic)
10454 {
10455     operand *right, *left, *result;
10456     sym_link *letype ;
10457     int size, offset;
10458     char *l;
10459     symbol *tlbl, *tlbl1 ;
10460
10461     /* if signed then we do it the hard way preserve the
10462     sign bit moving it inwards */
10463     letype = getSpec(operandType(IC_LEFT(ic)));
10464     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10465
10466     if (!SPEC_USIGN(letype)) {
10467         genSignedRightShift (ic);
10468         return ;
10469     }
10470
10471     /* signed & unsigned types are treated the same : i.e. the
10472     signed is NOT propagated inwards : quoting from the
10473     ANSI - standard : "for E1 >> E2, is equivalent to division
10474     by 2**E2 if unsigned or if it has a non-negative value,
10475     otherwise the result is implementation defined ", MY definition
10476     is that the sign does not get propagated */
10477
10478     right = IC_RIGHT(ic);
10479     left  = IC_LEFT(ic);
10480     result = IC_RESULT(ic);
10481
10482     pic16_aopOp(right,ic,FALSE);
10483
10484     /* if the shift count is known then do it 
10485     as efficiently as possible */
10486     if (AOP_TYPE(right) == AOP_LIT) {
10487         genRightShiftLiteral (left,right,result,ic, 0);
10488         return ;
10489     }
10490
10491     /* shift count is unknown then we have to form 
10492     a loop get the loop count in B : Note: we take
10493     only the lower order byte since shifting
10494     more that 32 bits make no sense anyway, ( the
10495     largest size of an object can be only 32 bits ) */  
10496
10497     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10498     pic16_emitcode("inc","b");
10499     pic16_aopOp(left,ic,FALSE);
10500     pic16_aopOp(result,ic,FALSE);
10501
10502     /* now move the left to the result if they are not the
10503     same */
10504     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10505         AOP_SIZE(result) > 1) {
10506
10507         size = AOP_SIZE(result);
10508         offset=0;
10509         while (size--) {
10510             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10511             if (*l == '@' && IS_AOP_PREG(result)) {
10512
10513                 pic16_emitcode("mov","a,%s",l);
10514                 pic16_aopPut(AOP(result),"a",offset);
10515             } else
10516                 pic16_aopPut(AOP(result),l,offset);
10517             offset++;
10518         }
10519     }
10520
10521     tlbl = newiTempLabel(NULL);
10522     tlbl1= newiTempLabel(NULL);
10523     size = AOP_SIZE(result);
10524     offset = size - 1;
10525
10526     /* if it is only one byte then */
10527     if (size == 1) {
10528
10529       tlbl = newiTempLabel(NULL);
10530       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10531         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10532         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10533       }
10534
10535       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10536       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10537       pic16_emitpLabel(tlbl->key);
10538       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10539       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10540       emitSKPC;
10541       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10542
10543       goto release ;
10544     }
10545
10546     reAdjustPreg(AOP(result));
10547     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10548     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10549     CLRC;
10550     while (size--) {
10551         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10552         MOVA(l);
10553         pic16_emitcode("rrc","a");         
10554         pic16_aopPut(AOP(result),"a",offset--);
10555     }
10556     reAdjustPreg(AOP(result));
10557
10558     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10559     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10560
10561 release:
10562     pic16_freeAsmop(left,NULL,ic,TRUE);
10563     pic16_freeAsmop (right,NULL,ic,TRUE);
10564     pic16_freeAsmop(result,NULL,ic,TRUE);
10565 }
10566 #endif
10567
10568 #if (USE_GENERIC_SIGNED_SHIFT)
10569 /*-----------------------------------------------------------------*/
10570 /* genGenericShift - generates code for left or right shifting     */
10571 /*-----------------------------------------------------------------*/
10572 static void genGenericShift (iCode *ic, int isShiftLeft) {
10573   operand *left,*right, *result;
10574   int offset;
10575   int sign, signedCount;
10576   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10577   PIC_OPCODE pos_shift, neg_shift;
10578
10579   FENTRY;
10580
10581   right = IC_RIGHT(ic);
10582   left  = IC_LEFT(ic);
10583   result = IC_RESULT(ic);
10584
10585   pic16_aopOp(right,ic,FALSE);
10586   pic16_aopOp(left,ic,FALSE);
10587   pic16_aopOp(result,ic,FALSE);
10588
10589   sign = !SPEC_USIGN(operandType (left));
10590   signedCount = !SPEC_USIGN(operandType (right));
10591
10592   /* if the shift count is known then do it 
10593      as efficiently as possible */
10594   if (AOP_TYPE(right) == AOP_LIT) {
10595     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10596     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10597     // we should modify right->aopu.aop_lit here!
10598     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10599     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10600     if (isShiftLeft)
10601       pic16_genLeftShiftLiteral (left,right,result,ic);
10602     else
10603       genRightShiftLiteral (left,right,result,ic, sign);
10604
10605     goto release;
10606   } // if (right is literal)
10607
10608   /* shift count is unknown then we have to form a loop.
10609    * Note: we take only the lower order byte since shifting
10610    * more than 32 bits make no sense anyway, ( the
10611    * largest size of an object can be only 32 bits )
10612    * Note: we perform arithmetic shifts if the left operand is
10613    * signed and we do an (effective) right shift, i. e. we
10614    * shift in the sign bit from the left. */
10615    
10616   label_complete = newiTempLabel ( NULL );
10617   label_loop_pos = newiTempLabel ( NULL );
10618   label_loop_neg = NULL;
10619   label_negative = NULL;
10620   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10621   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10622
10623   if (signedCount) {
10624     // additional labels needed
10625     label_loop_neg = newiTempLabel ( NULL );
10626     label_negative = newiTempLabel ( NULL );
10627   } // if
10628
10629   // copy source to result -- this will effectively truncate the left operand to the size of result!
10630   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10631   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10632   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10633     mov2f (AOP(result),AOP(left), offset);
10634   } // for
10635
10636   // if result is longer than left, fill with zeros (or sign)
10637   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10638     if (sign && AOP_SIZE(left) > 0) {
10639       // shift signed operand -- fill with sign
10640       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10641       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10642       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10643       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10644         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10645       } // for
10646     } else {
10647       // shift unsigned operand -- fill result with zeros
10648       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10649         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10650       } // for
10651     }
10652   } // if (size mismatch)
10653
10654   pic16_mov2w (AOP(right), 0);
10655   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10656   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10657   
10658 #if 0
10659   // perform a shift by one (shift count is positive)
10660   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10661   // 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])
10662   pic16_emitpLabel (label_loop_pos->key);
10663   emitCLRC;
10664   if (sign && (pos_shift == POC_RRCF)) {
10665     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10666     emitSETC;
10667   } // if
10668   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10669   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10670   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10671 #else
10672   // perform a shift by one (shift count is positive)
10673   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10674   // 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])
10675   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10676   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10677   emitCLRC;
10678   pic16_emitpLabel (label_loop_pos->key);
10679   if (sign && (pos_shift == POC_RRCF)) {
10680     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10681     emitSETC;
10682   } // if
10683   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10684   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10685   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10686   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10687 #endif
10688
10689   if (signedCount) {
10690     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10691
10692     pic16_emitpLabel (label_negative->key);
10693     // perform a shift by -1 (shift count is negative)
10694     // 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)
10695     emitCLRC;
10696     pic16_emitpLabel (label_loop_neg->key);
10697     if (sign && (neg_shift == POC_RRCF)) {
10698       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10699       emitSETC;
10700     } // if
10701     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10702     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10703     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10704     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10705   } // if (signedCount)
10706
10707   pic16_emitpLabel (label_complete->key);
10708
10709 release:
10710   pic16_freeAsmop (right,NULL,ic,TRUE);
10711   pic16_freeAsmop(left,NULL,ic,TRUE);
10712   pic16_freeAsmop(result,NULL,ic,TRUE);
10713 }
10714
10715 static void genLeftShift (iCode *ic) {
10716   genGenericShift (ic, 1);
10717 }
10718
10719 static void genRightShift (iCode *ic) {
10720   genGenericShift (ic, 0);
10721 }
10722 #endif
10723
10724
10725 void pic16_loadFSR0(operand *op)
10726 {
10727         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10728 }
10729
10730 /*-----------------------------------------------------------------*/
10731 /* genUnpackBits - generates code for unpacking bits               */
10732 /*-----------------------------------------------------------------*/
10733 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10734 {    
10735   int shCnt ;
10736   int rlen = 0 ;
10737   sym_link *etype, *letype;
10738   int blen=0, bstr=0;
10739   int lbstr;
10740   int offset = 0 ;
10741
10742     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10743     etype = getSpec(operandType(result));
10744     letype = getSpec(operandType(left));
10745     
10746 //    if(IS_BITFIELD(etype)) {
10747       blen = SPEC_BLEN(etype);
10748       bstr = SPEC_BSTR(etype);
10749 //    }
10750
10751     lbstr = SPEC_BSTR( letype );
10752
10753 #if 1
10754     if((blen == 1) && (bstr < 8)) {
10755       /* it is a single bit, so use the appropriate bit instructions */
10756       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10757
10758       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10759       
10760       if((ptype == POINTER) && (result)) {
10761         /* workaround to reduce the extra lfsr instruction */
10762         pic16_emitpcode(POC_BTFSC,
10763               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10764       } else {
10765         pic16_emitpcode(POC_BTFSC,
10766               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10767       }
10768         
10769       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10770
10771       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10772       return;
10773     }
10774
10775 #endif
10776
10777         /* the following call to pic16_loadFSR0 is temporary until
10778          * optimization to handle single bit assignments is added
10779          * to the function. Until then use the old safe way! -- VR */
10780         pic16_loadFSR0( left );
10781  
10782         /* read the first byte  */
10783         switch (ptype) {
10784                 case POINTER:
10785                 case IPOINTER:
10786                 case PPOINTER:
10787                 case FPOINTER:
10788                 case GPOINTER:
10789                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10790                         break;
10791                 case CPOINTER:
10792                         pic16_emitcode("clr","a");
10793                         pic16_emitcode("movc","a","@a+dptr");
10794                         break;
10795         }
10796         
10797
10798         /* if we have bitdisplacement then it fits   */
10799         /* into this byte completely or if length is */
10800         /* less than a byte                          */
10801         if ((shCnt = SPEC_BSTR(etype)) || 
10802                 (SPEC_BLEN(etype) <= 8))  {
10803
10804                 /* shift right acc */
10805                 AccRsh(shCnt, 0);
10806
10807                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10808                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10809
10810 /* VR -- normally I would use the following, but since we use the hack,
10811  * to avoid the masking from AccRsh, why not mask it right now? */
10812
10813 /*
10814                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10815 */
10816
10817                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10818           return ;
10819         }
10820
10821
10822
10823         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10824         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10825         exit(-1);
10826
10827     /* bit field did not fit in a byte  */
10828     rlen = SPEC_BLEN(etype) - 8;
10829     pic16_aopPut(AOP(result),"a",offset++);
10830
10831     while (1)  {
10832
10833         switch (ptype) {
10834         case POINTER:
10835         case IPOINTER:
10836             pic16_emitcode("inc","%s",rname);
10837             pic16_emitcode("mov","a,@%s",rname);
10838             break;
10839             
10840         case PPOINTER:
10841             pic16_emitcode("inc","%s",rname);
10842             pic16_emitcode("movx","a,@%s",rname);
10843             break;
10844
10845         case FPOINTER:
10846             pic16_emitcode("inc","dptr");
10847             pic16_emitcode("movx","a,@dptr");
10848             break;
10849             
10850         case CPOINTER:
10851             pic16_emitcode("clr","a");
10852             pic16_emitcode("inc","dptr");
10853             pic16_emitcode("movc","a","@a+dptr");
10854             break;
10855             
10856         case GPOINTER:
10857             pic16_emitcode("inc","dptr");
10858             pic16_emitcode("lcall","__gptrget");
10859             break;
10860         }
10861
10862         rlen -= 8;            
10863         /* if we are done */
10864         if ( rlen <= 0 )
10865             break ;
10866         
10867         pic16_aopPut(AOP(result),"a",offset++);
10868                               
10869     }
10870     
10871     if (rlen) {
10872         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10873         pic16_aopPut(AOP(result),"a",offset);          
10874     }
10875     
10876     return ;
10877 }
10878
10879
10880 static void genDataPointerGet(operand *left,
10881                               operand *result,
10882                               iCode *ic)
10883 {
10884   int size, offset = 0, leoffset=0 ;
10885
10886         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10887         pic16_aopOp(result, ic, FALSE);
10888
10889         size = AOP_SIZE(result);
10890 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10891
10892
10893 #if 0
10894         /* The following tests may save a redudant movff instruction when
10895          * accessing unions */
10896          
10897         /* if they are the same */
10898         if (operandsEqu (left, result)) {
10899                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10900                 goto release;
10901         }
10902 #endif
10903
10904 #if 0
10905         /* if they are the same registers */
10906         if (pic16_sameRegs(AOP(left),AOP(result))) {
10907                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10908                 goto release;
10909         }
10910 #endif
10911
10912 #if 1
10913         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10914                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10915                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10916                 goto release;
10917         }
10918 #endif
10919
10920
10921 #if 0
10922         if ( AOP_TYPE(left) == AOP_PCODE) {
10923                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
10924                                 AOP(left)->aopu.pcop->name,
10925                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
10926                                 PCOR(AOP(left)->aopu.pcop)->instance:
10927                                 PCOI(AOP(left)->aopu.pcop)->offset);
10928         }
10929 #endif
10930
10931         if(AOP(left)->aopu.pcop->type == PO_DIR)
10932                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10933
10934         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10935
10936         while (size--) {
10937                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10938                 
10939                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
10940                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
10941                         pic16_mov2w(AOP(left), offset); // patch 8
10942                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10943                 } else {
10944                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10945                                 pic16_popGet(AOP(left), offset), //patch 8
10946                                 pic16_popGet(AOP(result), offset)));
10947                 }
10948
10949                 offset++;
10950                 leoffset++;
10951         }
10952
10953 release:
10954     pic16_freeAsmop(result,NULL,ic,TRUE);
10955 }
10956
10957
10958
10959 /*-----------------------------------------------------------------*/
10960 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10961 /*-----------------------------------------------------------------*/
10962 static void genNearPointerGet (operand *left, 
10963                                operand *result, 
10964                                iCode *ic)
10965 {
10966   asmop *aop = NULL;
10967   //regs *preg = NULL ;
10968   sym_link *rtype, *retype;
10969   sym_link *ltype = operandType(left);    
10970
10971     FENTRY;
10972     
10973     rtype = operandType(result);
10974     retype= getSpec(rtype);
10975     
10976     pic16_aopOp(left,ic,FALSE);
10977
10978 //    pic16_DumpOp("(left)",left);
10979 //    pic16_DumpOp("(result)",result);
10980
10981     /* if left is rematerialisable and
10982      * result is not bit variable type and
10983      * the left is pointer to data space i.e
10984      * lower 128 bytes of space */
10985     
10986     if (AOP_TYPE(left) == AOP_PCODE
10987       && !IS_BITFIELD(retype)
10988       && DCL_TYPE(ltype) == POINTER) {
10989
10990         genDataPointerGet (left,result,ic);
10991         pic16_freeAsmop(left, NULL, ic, TRUE);
10992         return ;
10993     }
10994     
10995     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10996
10997     /* if the value is already in a pointer register
10998      * then don't need anything more */
10999     if (!AOP_INPREG(AOP(left))) {
11000       /* otherwise get a free pointer register */
11001       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11002                 
11003       /* VR -- the whole concept is to load FSR0 with the address of the symbol */
11004       /* bitfields will be handled by genUnpackBits */
11005       if(!IS_BITFIELD(retype)) {
11006
11007         if(is_LitAOp( AOP(left) )) {
11008           pic16_loadFSR0( left );
11009         } else {
11010             // set up FSR0 with address from left
11011             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11012             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11013         }
11014       }
11015     }
11016 //    else
11017 //    rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11018     
11019     pic16_aopOp (result,ic,FALSE);
11020     
11021     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11022
11023     /* if bitfield then unpack the bits */
11024     if (IS_BITFIELD(retype)) 
11025       genUnpackBits (result, left, NULL, POINTER);
11026     else {
11027       /* we have can just get the values */
11028       int size = AOP_SIZE(result);
11029       int offset = 0;   
11030         
11031       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11032
11033       /* fsr0 is loaded already -- VR */
11034 //      pic16_loadFSR0( left );
11035
11036 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
11037 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
11038       while(size--) {
11039         if(size) {
11040           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11041                 pic16_popGet(AOP(result), offset++)));
11042         } else {
11043           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11044                 pic16_popGet(AOP(result), offset++)));
11045         }
11046       }
11047 #if 0
11048 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
11049 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
11050       if(size)
11051         pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
11052 #endif
11053 /*
11054         while (size--) {
11055             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
11056
11057                 pic16_emitcode("mov","a,@%s",rname);
11058                 pic16_aopPut(AOP(result),"a",offset);
11059             } else {
11060                 sprintf(buffer,"@%s",rname);
11061                 pic16_aopPut(AOP(result),buffer,offset);
11062             }
11063             offset++ ;
11064             if (size)
11065                 pic16_emitcode("inc","%s",rname);
11066         }
11067 */
11068     }
11069
11070     /* now some housekeeping stuff */
11071     if (aop) {
11072       /* we had to allocate for this iCode */
11073       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11074       pic16_freeAsmop(NULL,aop,ic,TRUE);
11075     } else { 
11076       /* we did not allocate which means left
11077        * already in a pointer register, then
11078        * if size > 0 && this could be used again
11079        * we have to point it back to where it 
11080        * belongs */
11081       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11082       if (AOP_SIZE(result) > 1
11083         && !OP_SYMBOL(left)->remat
11084         && ( OP_SYMBOL(left)->liveTo > ic->seq
11085             || ic->depth )) {
11086 //        int size = AOP_SIZE(result) - 1;
11087 //        while (size--)
11088 //          pic16_emitcode("dec","%s",rname);
11089         }
11090     }
11091
11092     /* done */
11093     pic16_freeAsmop(left,NULL,ic,TRUE);
11094     pic16_freeAsmop(result,NULL,ic,TRUE);
11095 }
11096
11097 /*-----------------------------------------------------------------*/
11098 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
11099 /*-----------------------------------------------------------------*/
11100 static void genPagedPointerGet (operand *left, 
11101                                operand *result, 
11102                                iCode *ic)
11103 {
11104     asmop *aop = NULL;
11105     regs *preg = NULL ;
11106     char *rname ;
11107     sym_link *rtype, *retype;    
11108
11109     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11110
11111     rtype = operandType(result);
11112     retype= getSpec(rtype);
11113     
11114     pic16_aopOp(left,ic,FALSE);
11115
11116   /* if the value is already in a pointer register
11117        then don't need anything more */
11118     if (!AOP_INPREG(AOP(left))) {
11119         /* otherwise get a free pointer register */
11120         aop = newAsmop(0);
11121         preg = getFreePtr(ic,&aop,FALSE);
11122         pic16_emitcode("mov","%s,%s",
11123                 preg->name,
11124                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11125         rname = preg->name ;
11126     } else
11127         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11128     
11129     pic16_freeAsmop(left,NULL,ic,TRUE);
11130     pic16_aopOp (result,ic,FALSE);
11131
11132     /* if bitfield then unpack the bits */
11133     if (IS_BITFIELD(retype)) 
11134         genUnpackBits (result,left,rname,PPOINTER);
11135     else {
11136         /* we have can just get the values */
11137         int size = AOP_SIZE(result);
11138         int offset = 0 ;        
11139         
11140         while (size--) {
11141             
11142             pic16_emitcode("movx","a,@%s",rname);
11143             pic16_aopPut(AOP(result),"a",offset);
11144             
11145             offset++ ;
11146             
11147             if (size)
11148                 pic16_emitcode("inc","%s",rname);
11149         }
11150     }
11151
11152     /* now some housekeeping stuff */
11153     if (aop) {
11154         /* we had to allocate for this iCode */
11155         pic16_freeAsmop(NULL,aop,ic,TRUE);
11156     } else { 
11157         /* we did not allocate which means left
11158            already in a pointer register, then
11159            if size > 0 && this could be used again
11160            we have to point it back to where it 
11161            belongs */
11162         if (AOP_SIZE(result) > 1 &&
11163             !OP_SYMBOL(left)->remat &&
11164             ( OP_SYMBOL(left)->liveTo > ic->seq ||
11165               ic->depth )) {
11166             int size = AOP_SIZE(result) - 1;
11167             while (size--)
11168                 pic16_emitcode("dec","%s",rname);
11169         }
11170     }
11171
11172     /* done */
11173     pic16_freeAsmop(result,NULL,ic,TRUE);
11174     
11175         
11176 }
11177
11178 /*-----------------------------------------------------------------*/
11179 /* genFarPointerGet - gget value from far space                    */
11180 /*-----------------------------------------------------------------*/
11181 static void genFarPointerGet (operand *left,
11182                               operand *result, iCode *ic)
11183 {
11184     int size, offset ;
11185     sym_link *retype = getSpec(operandType(result));
11186
11187     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11188
11189     pic16_aopOp(left,ic,FALSE);
11190
11191     /* if the operand is already in dptr 
11192     then we do nothing else we move the value to dptr */
11193     if (AOP_TYPE(left) != AOP_STR) {
11194         /* if this is remateriazable */
11195         if (AOP_TYPE(left) == AOP_IMMD)
11196             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11197         else { /* we need to get it byte by byte */
11198             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11199             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11200             if (options.model == MODEL_FLAT24)
11201             {
11202                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11203             }
11204         }
11205     }
11206     /* so dptr know contains the address */
11207     pic16_freeAsmop(left,NULL,ic,TRUE);
11208     pic16_aopOp(result,ic,FALSE);
11209
11210     /* if bit then unpack */
11211     if (IS_BITFIELD(retype)) 
11212         genUnpackBits(result,left,"dptr",FPOINTER);
11213     else {
11214         size = AOP_SIZE(result);
11215         offset = 0 ;
11216
11217         while (size--) {
11218             pic16_emitcode("movx","a,@dptr");
11219             pic16_aopPut(AOP(result),"a",offset++);
11220             if (size)
11221                 pic16_emitcode("inc","dptr");
11222         }
11223     }
11224
11225     pic16_freeAsmop(result,NULL,ic,TRUE);
11226 }
11227 #if 0
11228 /*-----------------------------------------------------------------*/
11229 /* genCodePointerGet - get value from code space                  */
11230 /*-----------------------------------------------------------------*/
11231 static void genCodePointerGet (operand *left,
11232                                 operand *result, iCode *ic)
11233 {
11234     int size, offset ;
11235     sym_link *retype = getSpec(operandType(result));
11236
11237     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11238
11239     pic16_aopOp(left,ic,FALSE);
11240
11241     /* if the operand is already in dptr 
11242     then we do nothing else we move the value to dptr */
11243     if (AOP_TYPE(left) != AOP_STR) {
11244         /* if this is remateriazable */
11245         if (AOP_TYPE(left) == AOP_IMMD)
11246             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11247         else { /* we need to get it byte by byte */
11248             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11249             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11250             if (options.model == MODEL_FLAT24)
11251             {
11252                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11253             }
11254         }
11255     }
11256     /* so dptr know contains the address */
11257     pic16_freeAsmop(left,NULL,ic,TRUE);
11258     pic16_aopOp(result,ic,FALSE);
11259
11260     /* if bit then unpack */
11261     if (IS_BITFIELD(retype)) 
11262         genUnpackBits(result,left,"dptr",CPOINTER);
11263     else {
11264         size = AOP_SIZE(result);
11265         offset = 0 ;
11266
11267         while (size--) {
11268             pic16_emitcode("clr","a");
11269             pic16_emitcode("movc","a,@a+dptr");
11270             pic16_aopPut(AOP(result),"a",offset++);
11271             if (size)
11272                 pic16_emitcode("inc","dptr");
11273         }
11274     }
11275
11276     pic16_freeAsmop(result,NULL,ic,TRUE);
11277 }
11278 #endif
11279 #if 0
11280 /*-----------------------------------------------------------------*/
11281 /* genGenPointerGet - gget value from generic pointer space        */
11282 /*-----------------------------------------------------------------*/
11283 static void genGenPointerGet (operand *left,
11284                               operand *result, iCode *ic)
11285 {
11286   int size, offset, lit;
11287   sym_link *retype = getSpec(operandType(result));
11288
11289         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11290         pic16_aopOp(left,ic,FALSE);
11291         pic16_aopOp(result,ic,FALSE);
11292         size = AOP_SIZE(result);
11293
11294         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11295
11296         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11297
11298                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11299                 // load FSR0 from immediate
11300                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11301
11302 //              pic16_loadFSR0( left );
11303
11304                 offset = 0;
11305                 while(size--) {
11306                         if(size) {
11307                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11308                         } else {
11309                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11310                         }
11311                         offset++;
11312                 }
11313                 goto release;
11314
11315         }
11316         else { /* we need to get it byte by byte */
11317                 // set up FSR0 with address from left
11318                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11319                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11320
11321                 offset = 0 ;
11322
11323                 while(size--) {
11324                         if(size) {
11325                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11326                         } else {
11327                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11328                         }
11329                         offset++;
11330                 }
11331                 goto release;
11332         }
11333
11334   /* if bit then unpack */
11335         if (IS_BITFIELD(retype)) 
11336                 genUnpackBits(result,left,"BAD",GPOINTER);
11337
11338         release:
11339         pic16_freeAsmop(left,NULL,ic,TRUE);
11340         pic16_freeAsmop(result,NULL,ic,TRUE);
11341
11342 }
11343 #endif
11344
11345
11346 /*-----------------------------------------------------------------*/
11347 /* genGenPointerGet - gget value from generic pointer space        */
11348 /*-----------------------------------------------------------------*/
11349 static void genGenPointerGet (operand *left,
11350                               operand *result, iCode *ic)
11351 {
11352   int size, offset, lit;
11353   sym_link *retype = getSpec(operandType(result));
11354   char fgptrget[32];
11355
11356     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11357     pic16_aopOp(left,ic,FALSE);
11358     pic16_aopOp(result,ic,FALSE);
11359     size = AOP_SIZE(result);
11360
11361     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11362
11363     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11364
11365       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11366       // load FSR0 from immediate
11367       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11368
11369       werror(W_POSSBUG2, __FILE__, __LINE__);
11370
11371       offset = 0;
11372       while(size--) {
11373         if(size) {
11374           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11375         } else {
11376           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11377         }
11378         offset++;
11379       }
11380
11381       goto release;
11382
11383     } else { /* we need to get it byte by byte */
11384
11385       /* set up WREG:PRODL:FSR0L with address from left */
11386       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11387       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11388       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11389       
11390       switch( size ) {
11391         case 1: strcpy(fgptrget, "__gptrget1"); break;
11392         case 2: strcpy(fgptrget, "__gptrget2"); break;
11393         case 3: strcpy(fgptrget, "__gptrget3"); break;
11394         case 4: strcpy(fgptrget, "__gptrget4"); break;
11395         default:
11396           werror(W_POSSBUG2, __FILE__, __LINE__);
11397           abort();
11398       }
11399       
11400       pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11401       
11402       assignResultValue(result, 1);
11403       
11404       {
11405         symbol *sym;
11406
11407           sym = newSymbol( fgptrget, 0 );
11408           strcpy(sym->rname, fgptrget);
11409           checkAddSym(&externs, sym);
11410
11411 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11412       }
11413               
11414       goto release;
11415     }
11416
11417   /* if bit then unpack */
11418     if (IS_BITFIELD(retype)) 
11419       genUnpackBits(result,left,"BAD",GPOINTER);
11420
11421 release:
11422   pic16_freeAsmop(left,NULL,ic,TRUE);
11423   pic16_freeAsmop(result,NULL,ic,TRUE);
11424 }
11425
11426 /*-----------------------------------------------------------------*/
11427 /* genConstPointerGet - get value from const generic pointer space */
11428 /*-----------------------------------------------------------------*/
11429 static void genConstPointerGet (operand *left,
11430                                 operand *result, iCode *ic)
11431 {
11432   //sym_link *retype = getSpec(operandType(result));
11433   // symbol *albl = newiTempLabel(NULL);        // patch 15
11434   // symbol *blbl = newiTempLabel(NULL);        //
11435   // PIC_OPCODE poc;                            // patch 15
11436   int size;
11437   int offset = 0;
11438
11439   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11440   pic16_aopOp(left,ic,FALSE);
11441   pic16_aopOp(result,ic,TRUE);
11442   size = AOP_SIZE(result);
11443
11444   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11445
11446   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11447 #if 0                                                                   // patch 15
11448   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
11449   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
11450   pic16_emitpLabel(albl->key);
11451
11452   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
11453   
11454   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
11455   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
11456   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
11457   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
11458   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
11459
11460   pic16_emitpLabel(blbl->key);
11461
11462   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
11463 #endif                                                                  // patch 15
11464
11465
11466   // set up table pointer
11467   if( (AOP_TYPE(left) == AOP_PCODE) 
11468       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11469           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
11470     {
11471       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11472       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11473       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11474       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11475       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11476       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11477     }
11478   else
11479     {
11480       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11481       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11482       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11483     }
11484
11485
11486   while(size--)
11487     {
11488       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11489       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11490       offset++;
11491     }
11492     
11493   pic16_freeAsmop(left,NULL,ic,TRUE);
11494   pic16_freeAsmop(result,NULL,ic,TRUE);
11495
11496 }
11497
11498
11499 /*-----------------------------------------------------------------*/
11500 /* genPointerGet - generate code for pointer get                   */
11501 /*-----------------------------------------------------------------*/
11502 static void genPointerGet (iCode *ic)
11503 {
11504     operand *left, *result ;
11505     sym_link *type, *etype;
11506     int p_type;
11507
11508     FENTRY;
11509     
11510     left = IC_LEFT(ic);
11511     result = IC_RESULT(ic) ;
11512
11513     /* depending on the type of pointer we need to
11514     move it to the correct pointer register */
11515     type = operandType(left);
11516     etype = getSpec(type);
11517
11518 #if 0
11519     if (IS_PTR_CONST(type))
11520 #else
11521     if (IS_CODEPTR(type))
11522 #endif
11523       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11524
11525     /* if left is of type of pointer then it is simple */
11526     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11527         p_type = DCL_TYPE(type);
11528     else {
11529         /* we have to go by the storage class */
11530         p_type = PTR_TYPE(SPEC_OCLS(etype));
11531
11532         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11533
11534         if (SPEC_OCLS(etype)->codesp ) {
11535           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11536           //p_type = CPOINTER ; 
11537         }
11538         else
11539             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
11540               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11541                /*p_type = FPOINTER ;*/ 
11542             else
11543                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
11544                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11545 /*                  p_type = PPOINTER; */
11546                 else
11547                     if (SPEC_OCLS(etype) == idata )
11548                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11549 /*                      p_type = IPOINTER; */
11550                     else
11551                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11552 /*                      p_type = POINTER ; */
11553     }
11554
11555     /* now that we have the pointer type we assign
11556     the pointer values */
11557     switch (p_type) {
11558
11559     case POINTER:       
11560     case IPOINTER:
11561         genNearPointerGet (left,result,ic);
11562         break;
11563
11564     case PPOINTER:
11565         genPagedPointerGet(left,result,ic);
11566         break;
11567
11568     case FPOINTER:
11569         genFarPointerGet (left,result,ic);
11570         break;
11571
11572     case CPOINTER:
11573         genConstPointerGet (left,result,ic);
11574         //pic16_emitcodePointerGet (left,result,ic);
11575         break;
11576
11577     case GPOINTER:
11578 #if 0
11579       if (IS_PTR_CONST(type))
11580         genConstPointerGet (left,result,ic);
11581       else
11582 #endif
11583         genGenPointerGet (left,result,ic);
11584       break;
11585
11586     default:
11587       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11588               "genPointerGet: illegal pointer type");
11589     
11590     }
11591
11592 }
11593
11594 /*-----------------------------------------------------------------*/
11595 /* genPackBits - generates code for packed bit storage             */
11596 /*-----------------------------------------------------------------*/
11597 static void genPackBits (sym_link    *etype , operand *result,
11598                          operand *right ,
11599                          char *rname, int p_type)
11600 {
11601   int shCnt = 0 ;
11602   int offset = 0  ;
11603   int rLen = 0 ;
11604   int blen, bstr ;   
11605   sym_link *retype;
11606   char *l ;
11607
11608         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11609         blen = SPEC_BLEN(etype);
11610         bstr = SPEC_BSTR(etype);
11611
11612         retype = getSpec(operandType(right));
11613
11614         if(AOP_TYPE(right) == AOP_LIT) {
11615                 if((blen == 1) && (bstr < 8)) {
11616                   unsigned long lit;
11617                         /* it is a single bit, so use the appropriate bit instructions */
11618
11619                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11620
11621                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11622 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11623                         if((p_type == POINTER) && (result)) {
11624                                 /* workaround to reduce the extra lfsr instruction */
11625                                 if(lit) {
11626                                         pic16_emitpcode(POC_BSF,
11627                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11628                                 } else {
11629                                         pic16_emitpcode(POC_BCF,
11630                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11631                                 }
11632                         } else {
11633                                 pic16_loadFSR0( result );
11634                                 if(lit) {
11635                                         pic16_emitpcode(POC_BSF,
11636                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11637                                 } else {
11638                                         pic16_emitpcode(POC_BCF,
11639                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11640                                 }
11641                         }
11642         
11643                   return;
11644                 }
11645
11646                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11647                 offset++;
11648         } else
11649         if(IS_BITFIELD(retype) 
11650           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11651           && (blen == 1)) {
11652           int rblen, rbstr;
11653
11654             rblen = SPEC_BLEN( retype );
11655             rbstr = SPEC_BSTR( retype );
11656             
11657
11658             if(IS_BITFIELD(etype)) {
11659               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11660               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11661             } else {
11662               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11663             }
11664             
11665             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11666             
11667             if(IS_BITFIELD(etype)) {
11668               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11669             } else {
11670               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11671             }
11672
11673             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11674             
11675             return;
11676         } else
11677           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11678
11679         /* if the bit lenth is less than or    */
11680         /* it exactly fits a byte then         */
11681         if((shCnt=SPEC_BSTR(etype))
11682                 || SPEC_BLEN(etype) <= 8 )  {
11683
11684                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11685
11686                 /* shift left acc */
11687                 AccLsh(shCnt);
11688
11689                 /* using PRODL as a temporary register here */
11690                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11691
11692                 switch (p_type) {
11693                         case FPOINTER:
11694                         case POINTER:
11695                                 pic16_loadFSR0( result );
11696                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11697 //                              pic16_emitcode ("mov","b,a");
11698 //                              pic16_emitcode("mov","a,@%s",rname);
11699                                 break;
11700
11701                         case GPOINTER:
11702                                 werror(W_POSSBUG2, __FILE__, __LINE__);
11703                                 break;
11704
11705                 }
11706 #if 1
11707                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11708                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11709                                         (unsigned char)(0xff >> (8-bstr))) ));
11710                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
11711                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11712 #endif
11713
11714           return;
11715         }
11716
11717
11718         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11719         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11720         exit(-1);
11721
11722
11723     /* if we r done */
11724     if ( SPEC_BLEN(etype) <= 8 )
11725         return ;
11726
11727     pic16_emitcode("inc","%s",rname);
11728     rLen = SPEC_BLEN(etype) ;     
11729
11730
11731
11732     /* now generate for lengths greater than one byte */
11733     while (1) {
11734
11735         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
11736
11737         rLen -= 8 ;
11738         if (rLen <= 0 )
11739             break ;
11740
11741         switch (p_type) {
11742             case POINTER:
11743                 if (*l == '@') {
11744                     MOVA(l);
11745                     pic16_emitcode("mov","@%s,a",rname);
11746                 } else
11747                     pic16_emitcode("mov","@%s,%s",rname,l);
11748                 break;
11749
11750             case FPOINTER:
11751                 MOVA(l);
11752                 pic16_emitcode("movx","@dptr,a");
11753                 break;
11754
11755             case GPOINTER:
11756                 MOVA(l);
11757                 DEBUGpic16_emitcode(";lcall","__gptrput");
11758                 break;  
11759         }   
11760         pic16_emitcode ("inc","%s",rname);
11761     }
11762
11763     MOVA(l);
11764
11765     /* last last was not complete */
11766     if (rLen)   {
11767         /* save the byte & read byte */
11768         switch (p_type) {
11769             case POINTER:
11770                 pic16_emitcode ("mov","b,a");
11771                 pic16_emitcode("mov","a,@%s",rname);
11772                 break;
11773
11774             case FPOINTER:
11775                 pic16_emitcode ("mov","b,a");
11776                 pic16_emitcode("movx","a,@dptr");
11777                 break;
11778
11779             case GPOINTER:
11780                 pic16_emitcode ("push","b");
11781                 pic16_emitcode ("push","acc");
11782                 pic16_emitcode ("lcall","__gptrget");
11783                 pic16_emitcode ("pop","b");
11784                 break;
11785         }
11786
11787         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11788         pic16_emitcode ("orl","a,b");
11789     }
11790
11791     if (p_type == GPOINTER)
11792         pic16_emitcode("pop","b");
11793
11794     switch (p_type) {
11795
11796     case POINTER:
11797         pic16_emitcode("mov","@%s,a",rname);
11798         break;
11799         
11800     case FPOINTER:
11801         pic16_emitcode("movx","@dptr,a");
11802         break;
11803         
11804     case GPOINTER:
11805         DEBUGpic16_emitcode(";lcall","__gptrput");
11806         break;                  
11807     }
11808 }
11809 /*-----------------------------------------------------------------*/
11810 /* genDataPointerSet - remat pointer to data space                 */
11811 /*-----------------------------------------------------------------*/
11812 static void genDataPointerSet(operand *right,
11813                               operand *result,
11814                               iCode *ic)
11815 {
11816     int size, offset = 0, resoffset=0 ;
11817
11818     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11819     pic16_aopOp(right,ic,FALSE);
11820
11821     size = AOP_SIZE(right);
11822
11823 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11824
11825 #if 0
11826     if ( AOP_TYPE(result) == AOP_PCODE) {
11827       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11828               AOP(result)->aopu.pcop->name,
11829                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11830               PCOR(AOP(result)->aopu.pcop)->instance:
11831               PCOI(AOP(result)->aopu.pcop)->offset);
11832     }
11833 #endif
11834
11835         if(AOP(result)->aopu.pcop->type == PO_DIR)
11836                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11837
11838         while (size--) {
11839                 if (AOP_TYPE(right) == AOP_LIT) {
11840                   unsigned int lit;
11841
11842                     if(!IS_FLOAT(operandType( right )))
11843                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11844                     else {
11845                       union {
11846                         unsigned long lit_int;
11847                         float lit_float;
11848                       } info;
11849         
11850                         /* take care if literal is a float */
11851                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11852                         lit = info.lit_int;
11853                     }
11854
11855                     lit = lit >> (8*offset);
11856                     if(lit&0xff) {
11857                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11858                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11859                     } else {
11860                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11861                     }
11862                 } else {
11863                   pic16_mov2w(AOP(right), offset);
11864                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11865                 }
11866                 offset++;
11867                 resoffset++;
11868         }
11869
11870     pic16_freeAsmop(right,NULL,ic,TRUE);
11871 }
11872
11873
11874
11875 /*-----------------------------------------------------------------*/
11876 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11877 /*-----------------------------------------------------------------*/
11878 static void genNearPointerSet (operand *right,
11879                                operand *result, 
11880                                iCode *ic)
11881 {
11882   asmop *aop = NULL;
11883   char *l;
11884   sym_link *retype;
11885   sym_link *ptype = operandType(result);
11886   sym_link *resetype;
11887     
11888         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11889         retype= getSpec(operandType(right));
11890         resetype = getSpec(operandType(result));
11891   
11892         pic16_aopOp(result,ic,FALSE);
11893     
11894         /* if the result is rematerializable &
11895          * in data space & not a bit variable */
11896         
11897         /* and result is not a bit variable */
11898         if (AOP_TYPE(result) == AOP_PCODE
11899 //              && AOP_TYPE(result) == AOP_IMMD
11900                 && DCL_TYPE(ptype) == POINTER
11901                 && !IS_BITFIELD(retype)
11902                 && !IS_BITFIELD(resetype)) {
11903
11904                 genDataPointerSet (right,result,ic);
11905                 pic16_freeAsmop(result,NULL,ic,TRUE);
11906           return;
11907         }
11908
11909         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11910         pic16_aopOp(right,ic,FALSE);
11911         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11912
11913         /* if the value is already in a pointer register
11914          * then don't need anything more */
11915         if (!AOP_INPREG(AOP(result))) {
11916                 /* otherwise get a free pointer register */
11917                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11918
11919 //              if( (AOP_TYPE(result) == AOP_PCODE) 
11920 //                      && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
11921 //                              || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
11922                 if(is_LitAOp( AOP(result) ))
11923                 {
11924                   if(!IS_BITFIELD(resetype))
11925                         pic16_loadFSR0( result );  // patch 10
11926                 } else {
11927                   if(!IS_BITFIELD(resetype)) {
11928                         // set up FSR0 with address of result
11929                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11930                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11931                   }
11932                 }
11933
11934         }
11935 //      else
11936 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11937
11938         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11939
11940 //      pic16_loadFSR0( result );
11941
11942         /* if bitfield then unpack the bits */
11943         if (IS_BITFIELD(resetype)) {
11944                 genPackBits (resetype, result, right, NULL, POINTER);
11945         } else {
11946                 /* we have can just get the values */
11947           int size = AOP_SIZE(right);
11948           int offset = 0 ;    
11949
11950                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11951                 while (size--) {
11952                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11953                         if (*l == '@' ) {
11954                                 //MOVA(l);
11955                                 //pic16_emitcode("mov","@%s,a",rname);
11956                                 pic16_emitcode("movf","indf0,w ;1");
11957                         } else {
11958
11959                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
11960                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
11961                                         if (size) {                                                                     // 
11962                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
11963                                         } else {                                                                        // 
11964                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
11965                                         }                                                                               // 
11966                                 } else { // no literal                                                                  // 
11967                                         if(size) {                                                                      // 
11968                                                 pic16_emitpcode(POC_MOVFF,                                              // 
11969                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
11970                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
11971                                         } else {                                                                        // 
11972                                                 pic16_emitpcode(POC_MOVFF,                                              // 
11973                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
11974                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
11975                                         }                                                                               //
11976                                 }                                                                                       // patch 10
11977                         }
11978                         offset++;
11979                 }
11980         }
11981
11982         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11983         /* now some housekeeping stuff */
11984         if (aop) {
11985                 /* we had to allocate for this iCode */
11986                 pic16_freeAsmop(NULL,aop,ic,TRUE);
11987         } else { 
11988                 /* we did not allocate which means left
11989                  * already in a pointer register, then
11990                  * if size > 0 && this could be used again
11991                  * we have to point it back to where it 
11992                  * belongs */
11993                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11994                 if (AOP_SIZE(right) > 1
11995                         && !OP_SYMBOL(result)->remat
11996                         && ( OP_SYMBOL(result)->liveTo > ic->seq
11997                                 || ic->depth )) {
11998
11999                   int size = AOP_SIZE(right) - 1;
12000
12001                         while (size--)
12002                                 pic16_emitcode("decf","fsr0,f");
12003                         //pic16_emitcode("dec","%s",rname);
12004                 }
12005         }
12006
12007         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12008         /* done */
12009 //release:
12010         pic16_freeAsmop(right,NULL,ic,TRUE);
12011         pic16_freeAsmop(result,NULL,ic,TRUE);
12012 }
12013
12014 /*-----------------------------------------------------------------*/
12015 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
12016 /*-----------------------------------------------------------------*/
12017 static void genPagedPointerSet (operand *right,
12018                                operand *result, 
12019                                iCode *ic)
12020 {
12021     asmop *aop = NULL;
12022     regs *preg = NULL ;
12023     char *rname , *l;
12024     sym_link *retype;
12025        
12026     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12027
12028     retype= getSpec(operandType(right));
12029     
12030     pic16_aopOp(result,ic,FALSE);
12031     
12032     /* if the value is already in a pointer register
12033        then don't need anything more */
12034     if (!AOP_INPREG(AOP(result))) {
12035         /* otherwise get a free pointer register */
12036         aop = newAsmop(0);
12037         preg = getFreePtr(ic,&aop,FALSE);
12038         pic16_emitcode("mov","%s,%s",
12039                 preg->name,
12040                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12041         rname = preg->name ;
12042     } else
12043         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12044     
12045     pic16_freeAsmop(result,NULL,ic,TRUE);
12046     pic16_aopOp (right,ic,FALSE);
12047
12048     /* if bitfield then unpack the bits */
12049     if (IS_BITFIELD(retype)) 
12050         genPackBits (retype,result,right,rname,PPOINTER);
12051     else {
12052         /* we have can just get the values */
12053         int size = AOP_SIZE(right);
12054         int offset = 0 ;        
12055         
12056         while (size--) {
12057             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12058             
12059             MOVA(l);
12060             pic16_emitcode("movx","@%s,a",rname);
12061
12062             if (size)
12063                 pic16_emitcode("inc","%s",rname);
12064
12065             offset++;
12066         }
12067     }
12068     
12069     /* now some housekeeping stuff */
12070     if (aop) {
12071         /* we had to allocate for this iCode */
12072         pic16_freeAsmop(NULL,aop,ic,TRUE);
12073     } else { 
12074         /* we did not allocate which means left
12075            already in a pointer register, then
12076            if size > 0 && this could be used again
12077            we have to point it back to where it 
12078            belongs */
12079         if (AOP_SIZE(right) > 1 &&
12080             !OP_SYMBOL(result)->remat &&
12081             ( OP_SYMBOL(result)->liveTo > ic->seq ||
12082               ic->depth )) {
12083             int size = AOP_SIZE(right) - 1;
12084             while (size--)
12085                 pic16_emitcode("dec","%s",rname);
12086         }
12087     }
12088
12089     /* done */
12090     pic16_freeAsmop(right,NULL,ic,TRUE);
12091     
12092         
12093 }
12094
12095 /*-----------------------------------------------------------------*/
12096 /* genFarPointerSet - set value from far space                     */
12097 /*-----------------------------------------------------------------*/
12098 static void genFarPointerSet (operand *right,
12099                               operand *result, iCode *ic)
12100 {
12101     int size, offset ;
12102     sym_link *retype = getSpec(operandType(right));
12103
12104     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12105     pic16_aopOp(result,ic,FALSE);
12106
12107     /* if the operand is already in dptr 
12108     then we do nothing else we move the value to dptr */
12109     if (AOP_TYPE(result) != AOP_STR) {
12110         /* if this is remateriazable */
12111         if (AOP_TYPE(result) == AOP_IMMD)
12112             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12113         else { /* we need to get it byte by byte */
12114             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12115             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12116             if (options.model == MODEL_FLAT24)
12117             {
12118                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12119             }
12120         }
12121     }
12122     /* so dptr know contains the address */
12123     pic16_freeAsmop(result,NULL,ic,TRUE);
12124     pic16_aopOp(right,ic,FALSE);
12125
12126     /* if bit then unpack */
12127     if (IS_BITFIELD(retype)) 
12128         genPackBits(retype,result,right,"dptr",FPOINTER);
12129     else {
12130         size = AOP_SIZE(right);
12131         offset = 0 ;
12132
12133         while (size--) {
12134             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12135             MOVA(l);
12136             pic16_emitcode("movx","@dptr,a");
12137             if (size)
12138                 pic16_emitcode("inc","dptr");
12139         }
12140     }
12141
12142     pic16_freeAsmop(right,NULL,ic,TRUE);
12143 }
12144
12145 /*-----------------------------------------------------------------*/
12146 /* genGenPointerSet - set value from generic pointer space         */
12147 /*-----------------------------------------------------------------*/
12148 #if 0
12149 static void genGenPointerSet (operand *right,
12150                               operand *result, iCode *ic)
12151 {
12152         int i, size, offset, lit;
12153         sym_link *retype = getSpec(operandType(right));
12154
12155         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12156
12157         pic16_aopOp(result,ic,FALSE);
12158         pic16_aopOp(right,ic,FALSE);
12159         size = AOP_SIZE(right);
12160         offset = 0;
12161
12162         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12163
12164         /* if the operand is already in dptr 
12165                 then we do nothing else we move the value to dptr */
12166         if (AOP_TYPE(result) != AOP_STR) {
12167                 /* if this is remateriazable */
12168                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12169                 // WARNING: anythig until "else" is untested!
12170                 if (AOP_TYPE(result) == AOP_IMMD) {
12171                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12172                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12173                         // load FSR0 from immediate
12174                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12175                         offset = 0;
12176                         while(size--) {
12177                                 if(size) {
12178                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12179                                 } else {
12180                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12181                                 }
12182                                 offset++;
12183                         }
12184                         goto release;
12185                 }
12186                 else { /* we need to get it byte by byte */
12187                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12188                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12189
12190                         // set up FSR0 with address of result
12191                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12192                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12193
12194                         /* hack hack! see if this the FSR. If so don't load W */
12195                         if(AOP_TYPE(right) != AOP_ACC) {
12196
12197                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12198
12199                                 if(AOP_TYPE(right) == AOP_LIT)
12200                                 {
12201                                         // copy literal
12202                                         // note: pic16_popGet handles sign extension
12203                                         for(i=0;i<size;i++) {
12204                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12205                                                 if(i < size-1)
12206                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12207                                                 else
12208                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12209                                         }
12210                                 } else {
12211                                         // copy regs
12212
12213                                         for(i=0;i<size;i++) {
12214                                                 if(i < size-1)
12215                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12216                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12217                                                 else
12218                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12219                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12220                                         }
12221                                 }
12222                                 goto release;
12223                         } 
12224                         // right = ACC
12225                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12226                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12227                         goto release;
12228         } // if (AOP_TYPE(result) != AOP_IMMD)
12229
12230         } // if (AOP_TYPE(result) != AOP_STR)
12231         /* so dptr know contains the address */
12232
12233
12234         /* if bit then unpack */
12235         if (IS_BITFIELD(retype)) 
12236                 genPackBits(retype,result,right,"dptr",GPOINTER);
12237         else {
12238                 size = AOP_SIZE(right);
12239                 offset = 0 ;
12240
12241                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12242
12243                 // set up FSR0 with address of result
12244                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12245                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12246         
12247                 while (size--) {
12248                         if (AOP_TYPE(right) == AOP_LIT) {
12249                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12250                                 if (size) {
12251                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12252                                 } else {
12253                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12254                                 }
12255                         } else { // no literal
12256                                 if(size) {
12257                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12258                                 } else {
12259                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12260                                 }
12261                         }
12262                         offset++;
12263                 }
12264         }
12265
12266         release:
12267         pic16_freeAsmop(right,NULL,ic,TRUE);
12268         pic16_freeAsmop(result,NULL,ic,TRUE);
12269 }
12270 #endif
12271
12272 static void genGenPointerSet (operand *right,
12273                               operand *result, iCode *ic)
12274 {
12275   int size;
12276   sym_link *retype = getSpec(operandType(right));
12277   char fgptrput[32];
12278
12279     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12280
12281     pic16_aopOp(result,ic,FALSE);
12282     pic16_aopOp(right,ic,FALSE);
12283     size = AOP_SIZE(right);
12284
12285     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12286
12287
12288     /* if bit then unpack */
12289     if (IS_BITFIELD(retype)) {
12290 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12291       genPackBits(retype,result,right,"dptr",GPOINTER);
12292       goto release;
12293     }
12294
12295     size = AOP_SIZE(right);
12296
12297     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12298
12299
12300
12301     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12302
12303     /* value of right+0 is placed on stack, which will be retrieved
12304      * by the support function this restoring the stack. The important
12305      * thing is that there is no need to manually restore stack pointer
12306      * here */
12307     pushaop(AOP(right), 0);
12308 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12309     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12310     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12311     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12312     
12313     /* load address to write to in WREG:FSR0H:FSR0L */
12314     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12315                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12316     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12317                                 pic16_popCopyReg(&pic16_pc_prodl)));
12318     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12319     
12320
12321     /* put code here */
12322     switch (size) {
12323       case 1: strcpy(fgptrput, "__gptrput1"); break;
12324       case 2: strcpy(fgptrput, "__gptrput2"); break;
12325       case 3: strcpy(fgptrput, "__gptrput3"); break;
12326       case 4: strcpy(fgptrput, "__gptrput4"); break;
12327       default:
12328         werror(W_POSSBUG2, __FILE__, __LINE__);
12329         abort();
12330     }
12331     
12332     pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12333     
12334     {
12335       symbol *sym;
12336                   
12337         sym = newSymbol( fgptrput, 0 );
12338         strcpy(sym->rname, fgptrput);
12339         checkAddSym(&externs, sym);
12340     }
12341
12342 release:
12343     pic16_freeAsmop(right,NULL,ic,TRUE);
12344     pic16_freeAsmop(result,NULL,ic,TRUE);
12345 }
12346
12347 /*-----------------------------------------------------------------*/
12348 /* genPointerSet - stores the value into a pointer location        */
12349 /*-----------------------------------------------------------------*/
12350 static void genPointerSet (iCode *ic)
12351 {    
12352   operand *right, *result ;
12353   sym_link *type, *etype;
12354   int p_type;
12355
12356     FENTRY;
12357
12358     right = IC_RIGHT(ic);
12359     result = IC_RESULT(ic) ;
12360
12361     /* depending on the type of pointer we need to
12362     move it to the correct pointer register */
12363     type = operandType(result);
12364     etype = getSpec(type);
12365     /* if left is of type of pointer then it is simple */
12366     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12367         p_type = DCL_TYPE(type);
12368     }
12369     else {
12370         /* we have to go by the storage class */
12371         p_type = PTR_TYPE(SPEC_OCLS(etype));
12372
12373 /*      if (SPEC_OCLS(etype)->codesp ) { */
12374 /*          p_type = CPOINTER ;  */
12375 /*      } */
12376 /*      else */
12377 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12378 /*              p_type = FPOINTER ; */
12379 /*          else */
12380 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12381 /*                  p_type = PPOINTER ; */
12382 /*              else */
12383 /*                  if (SPEC_OCLS(etype) == idata ) */
12384 /*                      p_type = IPOINTER ; */
12385 /*                  else */
12386 /*                      p_type = POINTER ; */
12387     }
12388
12389     /* now that we have the pointer type we assign
12390     the pointer values */
12391     switch (p_type) {
12392
12393     case POINTER:
12394     case IPOINTER:
12395         genNearPointerSet (right,result,ic);
12396         break;
12397
12398     case PPOINTER:
12399         genPagedPointerSet (right,result,ic);
12400         break;
12401
12402     case FPOINTER:
12403         genFarPointerSet (right,result,ic);
12404         break;
12405
12406     case GPOINTER:
12407         genGenPointerSet (right,result,ic);
12408         break;
12409
12410     default:
12411       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12412               "genPointerSet: illegal pointer type");
12413     }
12414 }
12415
12416 /*-----------------------------------------------------------------*/
12417 /* genIfx - generate code for Ifx statement                        */
12418 /*-----------------------------------------------------------------*/
12419 static void genIfx (iCode *ic, iCode *popIc)
12420 {
12421   operand *cond = IC_COND(ic);
12422   int isbit =0;
12423
12424     FENTRY;
12425
12426     pic16_aopOp(cond,ic,FALSE);
12427
12428     /* get the value into acc */
12429     if (AOP_TYPE(cond) != AOP_CRY)
12430       pic16_toBoolean(cond);
12431     else
12432       isbit = 1;
12433     /* the result is now in the accumulator */
12434     pic16_freeAsmop(cond,NULL,ic,TRUE);
12435
12436     /* if there was something to be popped then do it */
12437     if (popIc)
12438       genIpop(popIc);
12439
12440     /* if the condition is  a bit variable */
12441     if (isbit && IS_ITEMP(cond) && 
12442         SPIL_LOC(cond)) {
12443       genIfxJump(ic,"c");
12444       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12445     } else {
12446       if (isbit && !IS_ITEMP(cond))
12447         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12448         else
12449         genIfxJump(ic,"a");
12450     }
12451     ic->generated = 1;
12452 }
12453
12454 /*-----------------------------------------------------------------*/
12455 /* genAddrOf - generates code for address of                       */
12456 /*-----------------------------------------------------------------*/
12457 static void genAddrOf (iCode *ic)
12458 {
12459   operand *result, *left;
12460   int size;
12461   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12462   pCodeOp *pcop0, *pcop1, *pcop2;
12463
12464     FENTRY;
12465
12466     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12467
12468     sym = OP_SYMBOL( IC_LEFT(ic) );
12469     
12470     if(sym->onStack) {
12471       /* get address of symbol on stack */
12472       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12473 #if 0
12474       fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12475                   OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12476 #endif
12477
12478       // operands on stack are accessible via "FSR2 + index" with index
12479       // starting at 2 for arguments and growing from 0 downwards for
12480       // local variables (index == 0 is not assigned so we add one here)
12481       {
12482         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12483         if (soffs <= 0) {
12484           assert (soffs < 0);
12485           soffs++;
12486         } // if
12487         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12488         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12489         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(&pic16_pc_fsr2l));
12490         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12491         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12492         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(&pic16_pc_fsr2h));
12493         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12494       }
12495
12496       goto release;
12497     }
12498         
12499 //      if(pic16_debug_verbose) {
12500 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12501 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12502 //      }
12503         
12504     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12505     size = AOP_SIZE(IC_RESULT(ic));
12506
12507
12508     /* Assume that what we want the address of is in data space
12509      * since there is no stack on the PIC, yet! -- VR */
12510   
12511     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12512     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12513     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12514         
12515     if (size == 3) {
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       pic16_emitpcode(POC_MOVLW, pcop2);
12521       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12522     } else
12523     if (size == 2) {
12524       pic16_emitpcode(POC_MOVLW, pcop0);
12525       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12526       pic16_emitpcode(POC_MOVLW, pcop1);
12527     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12528     } else {
12529       pic16_emitpcode(POC_MOVLW, pcop0);
12530       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12531     }
12532
12533     pic16_freeAsmop(left, NULL, ic, FALSE);
12534 release:
12535     pic16_freeAsmop(result,NULL,ic,TRUE);
12536 }
12537
12538
12539 #if 0
12540 /*-----------------------------------------------------------------*/
12541 /* genFarFarAssign - assignment when both are in far space         */
12542 /*-----------------------------------------------------------------*/
12543 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12544 {
12545     int size = AOP_SIZE(right);
12546     int offset = 0;
12547     char *l ;
12548     /* first push the right side on to the stack */
12549     while (size--) {
12550         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12551         MOVA(l);
12552         pic16_emitcode ("push","acc");
12553     }
12554     
12555     pic16_freeAsmop(right,NULL,ic,FALSE);
12556     /* now assign DPTR to result */
12557     pic16_aopOp(result,ic,FALSE);
12558     size = AOP_SIZE(result);
12559     while (size--) {
12560         pic16_emitcode ("pop","acc");
12561         pic16_aopPut(AOP(result),"a",--offset);
12562     }
12563     pic16_freeAsmop(result,NULL,ic,FALSE);
12564         
12565 }
12566 #endif
12567
12568 /*-----------------------------------------------------------------*/
12569 /* genAssign - generate code for assignment                        */
12570 /*-----------------------------------------------------------------*/
12571 static void genAssign (iCode *ic)
12572 {
12573   operand *result, *right;
12574   int size, offset,know_W;
12575   unsigned long lit = 0L;
12576
12577   result = IC_RESULT(ic);
12578   right  = IC_RIGHT(ic) ;
12579
12580   FENTRY;
12581   
12582   /* if they are the same */
12583   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12584     return ;
12585
12586   /* reversed order operands are aopOp'ed so that result operand
12587    * is effective in case right is a stack symbol. This maneauver
12588    * allows to use the _G.resDirect flag later */
12589   pic16_aopOp(result,ic,TRUE);
12590   pic16_aopOp(right,ic,FALSE);
12591
12592   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12593
12594   /* if they are the same registers */
12595   if (pic16_sameRegs(AOP(right),AOP(result)))
12596     goto release;
12597
12598   /* if the result is a bit */
12599   if (AOP_TYPE(result) == AOP_CRY) {
12600     /* if the right size is a literal then
12601        we know what the value is */
12602     if (AOP_TYPE(right) == AOP_LIT) {
12603           
12604       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12605                   pic16_popGet(AOP(result),0));
12606
12607       if (((int) operandLitValue(right))) 
12608         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12609                        AOP(result)->aopu.aop_dir,
12610                        AOP(result)->aopu.aop_dir);
12611       else
12612         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12613                        AOP(result)->aopu.aop_dir,
12614                        AOP(result)->aopu.aop_dir);
12615       goto release;
12616     }
12617
12618     /* the right is also a bit variable */
12619     if (AOP_TYPE(right) == AOP_CRY) {
12620       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12621       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12622       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12623
12624       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12625                      AOP(result)->aopu.aop_dir,
12626                      AOP(result)->aopu.aop_dir);
12627       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12628                      AOP(right)->aopu.aop_dir,
12629                      AOP(right)->aopu.aop_dir);
12630       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12631                      AOP(result)->aopu.aop_dir,
12632                      AOP(result)->aopu.aop_dir);
12633       goto release ;
12634     }
12635
12636     /* we need to or */
12637     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12638     pic16_toBoolean(right);
12639     emitSKPZ;
12640     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12641     //pic16_aopPut(AOP(result),"a",0);
12642     goto release ;
12643   }
12644
12645   /* bit variables done */
12646   /* general case */
12647   size = AOP_SIZE(result);
12648   offset = 0 ;
12649
12650   if(AOP_TYPE(right) == AOP_LIT) {
12651         if(!IS_FLOAT(operandType( right )))
12652                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12653         else {
12654            union {
12655               unsigned long lit_int;
12656               float lit_float;
12657             } info;
12658         
12659                 /* take care if literal is a float */
12660                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12661                 lit = info.lit_int;
12662         }
12663   }
12664
12665 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12666 //                      sizeof(unsigned long int), sizeof(float));
12667
12668
12669   if (AOP_TYPE(right) == AOP_REG) {
12670     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12671     while (size--) {
12672       
12673       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12674     } // while
12675     goto release;
12676   }
12677
12678   if(AOP_TYPE(right) != AOP_LIT
12679         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12680         && !IS_FUNC(OP_SYM_TYPE(right))
12681         ) {
12682         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12683         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12684
12685         // set up table pointer
12686         if(is_LitOp(right)) {
12687 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12688                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12689                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12690                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12691                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12692                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12693                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12694         } else {
12695 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12696                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12697                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12698                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12699                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12700                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12701                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12702         }
12703
12704         size = min(AOP_SIZE(right), AOP_SIZE(result));
12705         while(size--) {
12706                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12707                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12708                         pic16_popGet(AOP(result),offset)));
12709                 offset++;
12710         }
12711
12712         if(AOP_SIZE(result) > AOP_SIZE(right)) {
12713                 size = AOP_SIZE(result) - AOP_SIZE(right);
12714                 while(size--) {
12715                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12716                         offset++;
12717                 }
12718         }
12719         goto release;
12720   }
12721
12722
12723
12724 #if 0
12725 /* VR - What is this?! */
12726   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12727     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12728     if(aopIdx(AOP(result),0) == 4) {
12729
12730       /* this is a workaround to save value of right into wreg too,
12731        * value of wreg is going to be used later */
12732       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12733       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12734       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12735       goto release;
12736     } else
12737 //      assert(0);
12738       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12739   }
12740 #endif
12741
12742   know_W=-1;
12743   while (size--) {
12744   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12745     if(AOP_TYPE(right) == AOP_LIT) {
12746       if(lit&0xff) {
12747         if(know_W != (lit&0xff))
12748           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12749         know_W = lit&0xff;
12750         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12751       } else
12752         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12753
12754       lit >>= 8;
12755
12756     } else if (AOP_TYPE(right) == AOP_CRY) {
12757       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12758       if(offset == 0) {
12759         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12760         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12761         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12762       }
12763     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12764         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12765         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12766     } else {
12767       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12768
12769       if(!_G.resDirect)         /* use this aopForSym feature */
12770         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12771     }
12772             
12773     offset++;
12774   }
12775   
12776  release:
12777   pic16_freeAsmop (right,NULL,ic,FALSE);
12778   pic16_freeAsmop (result,NULL,ic,TRUE);
12779 }   
12780
12781 /*-----------------------------------------------------------------*/
12782 /* genJumpTab - generates code for jump table                       */
12783 /*-----------------------------------------------------------------*/
12784 static void genJumpTab (iCode *ic)
12785 {
12786   symbol *jtab;
12787   char *l;
12788   pCodeOp *jt_offs;
12789   pCodeOp *jt_offs_hi;
12790   pCodeOp *jt_label;
12791
12792     FENTRY;
12793
12794     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12795     /* get the condition into accumulator */
12796     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12797     MOVA(l);
12798     /* multiply by three */
12799     pic16_emitcode("add","a,acc");
12800     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12801
12802     jtab = newiTempLabel(NULL);
12803     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12804     pic16_emitcode("jmp","@a+dptr");
12805     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12806
12807 #if 0
12808     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12809     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12810     emitSKPNC;
12811     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12812     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12813     pic16_emitpLabel(jtab->key);
12814
12815 #else
12816
12817     jt_offs = pic16_popGetTempReg(0);
12818     jt_offs_hi = pic16_popGetTempReg(1);
12819     jt_label = pic16_popGetLabel (jtab->key);
12820     //fprintf (stderr, "Creating jump table...\n");
12821
12822     // calculate offset into jump table (idx * sizeof (GOTO))
12823     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12824     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12825     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12826     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12827     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12828     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12829     pic16_emitpcode(POC_MOVWF , jt_offs);
12830
12831     // prepare PCLATx (set to first entry in jump table)
12832     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12833     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12834     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12835     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12836     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12837
12838     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12839     pic16_emitpcode(POC_ADDWF , jt_offs);
12840     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12841     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12842     emitSKPNC;
12843     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12844
12845     // release temporaries and prepare jump into table (new PCL --> WREG)
12846     pic16_emitpcode(POC_MOVFW , jt_offs);
12847     pic16_popReleaseTempReg (jt_offs_hi, 1);
12848     pic16_popReleaseTempReg (jt_offs, 0);
12849
12850     // jump into the table
12851     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12852
12853     pic16_emitpLabelFORCE(jtab->key);
12854
12855 #endif
12856     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12857
12858     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12859     /* now generate the jump labels */
12860     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12861          jtab = setNextItem(IC_JTLABELS(ic))) {
12862 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12863         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12864         
12865     }
12866     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12867
12868 }
12869
12870 /*-----------------------------------------------------------------*/
12871 /* genMixedOperation - gen code for operators between mixed types  */
12872 /*-----------------------------------------------------------------*/
12873 /*
12874   TSD - Written for the PIC port - but this unfortunately is buggy.
12875   This routine is good in that it is able to efficiently promote 
12876   types to different (larger) sizes. Unfortunately, the temporary
12877   variables that are optimized out by this routine are sometimes
12878   used in other places. So until I know how to really parse the 
12879   iCode tree, I'm going to not be using this routine :(.
12880 */
12881 static int genMixedOperation (iCode *ic)
12882 {
12883 #if 0
12884   operand *result = IC_RESULT(ic);
12885   sym_link *ctype = operandType(IC_LEFT(ic));
12886   operand *right = IC_RIGHT(ic);
12887   int ret = 0;
12888   int big,small;
12889   int offset;
12890
12891   iCode *nextic;
12892   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12893
12894   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12895
12896   nextic = ic->next;
12897   if(!nextic)
12898     return 0;
12899
12900   nextright = IC_RIGHT(nextic);
12901   nextleft  = IC_LEFT(nextic);
12902   nextresult = IC_RESULT(nextic);
12903
12904   pic16_aopOp(right,ic,FALSE);
12905   pic16_aopOp(result,ic,FALSE);
12906   pic16_aopOp(nextright,  nextic, FALSE);
12907   pic16_aopOp(nextleft,   nextic, FALSE);
12908   pic16_aopOp(nextresult, nextic, FALSE);
12909
12910   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12911
12912     operand *t = right;
12913     right = nextright;
12914     nextright = t; 
12915
12916     pic16_emitcode(";remove right +","");
12917
12918   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12919 /*
12920     operand *t = right;
12921     right = nextleft;
12922     nextleft = t; 
12923 */
12924     pic16_emitcode(";remove left +","");
12925   } else
12926     return 0;
12927
12928   big = AOP_SIZE(nextleft);
12929   small = AOP_SIZE(nextright);
12930
12931   switch(nextic->op) {
12932
12933   case '+':
12934     pic16_emitcode(";optimize a +","");
12935     /* if unsigned or not an integral type */
12936     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12937       pic16_emitcode(";add a bit to something","");
12938     } else {
12939
12940       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12941
12942       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12943         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12944         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12945       } else
12946         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12947
12948       offset = 0;
12949       while(--big) {
12950
12951         offset++;
12952
12953         if(--small) {
12954           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12955             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12956             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12957           }
12958
12959           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12960           emitSKPNC;
12961           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12962                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12963                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12964           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12965           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12966
12967         } else {
12968           pic16_emitcode("rlf","known_zero,w");
12969
12970           /*
12971             if right is signed
12972               btfsc  right,7
12973                addlw ff
12974           */
12975           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12976             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12977             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12978           } else {
12979             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12980           }
12981         }
12982       }
12983       ret = 1;
12984     }
12985   }
12986   ret = 1;
12987
12988 release:
12989   pic16_freeAsmop(right,NULL,ic,TRUE);
12990   pic16_freeAsmop(result,NULL,ic,TRUE);
12991   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12992   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12993   if(ret)
12994     nextic->generated = 1;
12995
12996   return ret;
12997 #else
12998   return 0;
12999 #endif
13000 }
13001 /*-----------------------------------------------------------------*/
13002 /* genCast - gen code for casting                                  */
13003 /*-----------------------------------------------------------------*/
13004 static void genCast (iCode *ic)
13005 {
13006   operand *result = IC_RESULT(ic);
13007   sym_link *ctype = operandType(IC_LEFT(ic));
13008   sym_link *rtype = operandType(IC_RIGHT(ic));
13009   sym_link *restype = operandType(IC_RESULT(ic));
13010   operand *right = IC_RIGHT(ic);
13011   int size, offset ;
13012
13013
13014     FENTRY;
13015
13016         /* if they are equivalent then do nothing */
13017 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13018 //              return ;
13019
13020         pic16_aopOp(right,ic,FALSE) ;
13021         pic16_aopOp(result,ic,FALSE);
13022
13023         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13024
13025
13026         /* if the result is a bit */
13027         if (AOP_TYPE(result) == AOP_CRY) {
13028         
13029                 /* if the right size is a literal then
13030                  * we know what the value is */
13031                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13032
13033                 if (AOP_TYPE(right) == AOP_LIT) {
13034                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13035                                 pic16_popGet(AOP(result),0));
13036
13037                         if (((int) operandLitValue(right))) 
13038                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13039                                         AOP(result)->aopu.aop_dir,
13040                                         AOP(result)->aopu.aop_dir);
13041                         else
13042                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13043                                         AOP(result)->aopu.aop_dir,
13044                                         AOP(result)->aopu.aop_dir);
13045                         goto release;
13046                 }
13047
13048                 /* the right is also a bit variable */
13049                 if (AOP_TYPE(right) == AOP_CRY) {
13050                         emitCLRC;
13051                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13052
13053                         pic16_emitcode("clrc","");
13054                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13055                                 AOP(right)->aopu.aop_dir,
13056                                 AOP(right)->aopu.aop_dir);
13057                         pic16_aopPut(AOP(result),"c",0);
13058                         goto release ;
13059                 }
13060
13061                 /* we need to or */
13062                 if (AOP_TYPE(right) == AOP_REG) {
13063                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
13064                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13065                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
13066                 }
13067                 pic16_toBoolean(right);
13068                 pic16_aopPut(AOP(result),"a",0);
13069                 goto release ;
13070         }
13071
13072         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13073           int offset = 1;
13074
13075                 size = AOP_SIZE(result);
13076
13077                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13078
13079                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
13080                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13081                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
13082
13083                 while (size--)
13084                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13085
13086                 goto release;
13087         }
13088
13089         if(IS_BITFIELD(getSpec(restype))
13090           && IS_BITFIELD(getSpec(rtype))) {
13091           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13092         }
13093
13094         /* if they are the same size : or less */
13095         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13096
13097                 /* if they are in the same place */
13098                 if (pic16_sameRegs(AOP(right),AOP(result)))
13099                         goto release;
13100
13101                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13102 #if 0
13103                 if (IS_PTR_CONST(rtype))
13104 #else
13105                 if (IS_CODEPTR(rtype))
13106 #endif
13107                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13108
13109 #if 0
13110                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13111 #else
13112                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13113 #endif
13114                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13115
13116 #if 0
13117                 if(AOP_TYPE(right) == AOP_IMMD) {
13118                   pCodeOp *pcop0, *pcop1, *pcop2;
13119                   symbol *sym = OP_SYMBOL( right );
13120
13121                         size = AOP_SIZE(result);
13122                         /* low */
13123                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13124                         /* high */
13125                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13126                         /* upper */
13127                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13128         
13129                         if (size == 3) {
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                                 pic16_emitpcode(POC_MOVLW, pcop2);
13135                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13136                         } else
13137                         if (size == 2) {
13138                                 pic16_emitpcode(POC_MOVLW, pcop0);
13139                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13140                                 pic16_emitpcode(POC_MOVLW, pcop1);
13141                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13142                         } else {
13143                                 pic16_emitpcode(POC_MOVLW, pcop0);
13144                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13145                         }
13146                 } else
13147 #endif
13148                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13149                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13150                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13151                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13152                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13153                         if(AOP_SIZE(result) <2)
13154                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13155                 } else {
13156                         /* if they in different places then copy */
13157                         size = AOP_SIZE(result);
13158                         offset = 0 ;
13159                         while (size--) {
13160                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13161                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13162                                 offset++;
13163                         }
13164                 }
13165                 goto release;
13166         }
13167
13168         /* if the result is of type pointer */
13169         if (IS_PTR(ctype)) {
13170           int p_type;
13171           sym_link *type = operandType(right);
13172           sym_link *etype = getSpec(type);
13173
13174                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13175
13176                 /* pointer to generic pointer */
13177                 if (IS_GENPTR(ctype)) {
13178                   char *l = zero;
13179             
13180                         if (IS_PTR(type)) 
13181                                 p_type = DCL_TYPE(type);
13182                         else {
13183                 /* we have to go by the storage class */
13184                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13185
13186 /*              if (SPEC_OCLS(etype)->codesp )  */
13187 /*                  p_type = CPOINTER ;  */
13188 /*              else */
13189 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13190 /*                      p_type = FPOINTER ; */
13191 /*                  else */
13192 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13193 /*                          p_type = PPOINTER; */
13194 /*                      else */
13195 /*                          if (SPEC_OCLS(etype) == idata ) */
13196 /*                              p_type = IPOINTER ; */
13197 /*                          else */
13198 /*                              p_type = POINTER ; */
13199             }
13200                 
13201             /* the first two bytes are known */
13202       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13203             size = GPTRSIZE - 1; 
13204             offset = 0 ;
13205             while (size--) {
13206               if(offset < AOP_SIZE(right)) {
13207                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13208                 mov2f(AOP(result), AOP(right), offset);
13209 /*
13210                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13211                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13212                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13213                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13214                 } else { 
13215                   
13216                   pic16_aopPut(AOP(result),
13217                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13218                          offset);
13219                 }
13220 */
13221               } else 
13222                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13223               offset++;
13224             }
13225             /* the last byte depending on type */
13226             switch (p_type) {
13227             case IPOINTER:
13228             case POINTER:
13229                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13230                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13231 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13232                 break;
13233
13234             case CPOINTER:
13235                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13236                 break;
13237
13238             case FPOINTER:
13239               pic16_emitcode(";BUG!? ","%d",__LINE__);
13240                 l = one;
13241                 break;
13242             case PPOINTER:
13243               pic16_emitcode(";BUG!? ","%d",__LINE__);
13244                 l = "#0x03";
13245                 break;
13246
13247             case GPOINTER:
13248               pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13249               break;
13250               
13251             default:
13252                 /* this should never happen */
13253                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13254                        "got unknown pointer type");
13255                 exit(1);
13256             }
13257             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13258             goto release ;
13259         }
13260         
13261         /* just copy the pointers */
13262         size = AOP_SIZE(result);
13263         offset = 0 ;
13264         while (size--) {
13265             pic16_aopPut(AOP(result),
13266                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13267                    offset);
13268             offset++;
13269         }
13270         goto release ;
13271     }
13272     
13273
13274
13275     /* so we now know that the size of destination is greater
13276     than the size of the source.
13277     Now, if the next iCode is an operator then we might be
13278     able to optimize the operation without performing a cast.
13279     */
13280     if(genMixedOperation(ic))
13281       goto release;
13282
13283     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13284     
13285     /* we move to result for the size of source */
13286     size = AOP_SIZE(right);
13287     offset = 0 ;
13288     while (size--) {
13289       mov2f(AOP(result), AOP(right), offset);
13290       offset++;
13291     }
13292
13293     /* now depending on the sign of the destination */
13294     size = AOP_SIZE(result) - AOP_SIZE(right);
13295     /* if unsigned or not an integral type */
13296     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13297       while (size--)
13298         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13299     } else {
13300       /* we need to extend the sign :( */
13301
13302       if(size == 1) {
13303         /* Save one instruction of casting char to int */
13304         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13305         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13306         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
13307       } else {
13308         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13309
13310         if(offset)
13311           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13312         else
13313           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13314         
13315         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13316
13317         while (size--)
13318           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13319       }
13320     }
13321
13322 release:
13323     pic16_freeAsmop(right,NULL,ic,TRUE);
13324     pic16_freeAsmop(result,NULL,ic,TRUE);
13325
13326 }
13327
13328 /*-----------------------------------------------------------------*/
13329 /* genDjnz - generate decrement & jump if not zero instrucion      */
13330 /*-----------------------------------------------------------------*/
13331 static int genDjnz (iCode *ic, iCode *ifx)
13332 {
13333     symbol *lbl, *lbl1;
13334     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13335
13336     if (!ifx)
13337         return 0;
13338     
13339     /* if the if condition has a false label
13340        then we cannot save */
13341     if (IC_FALSE(ifx))
13342         return 0;
13343
13344     /* if the minus is not of the form 
13345        a = a - 1 */
13346     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13347         !IS_OP_LITERAL(IC_RIGHT(ic)))
13348         return 0;
13349
13350     if (operandLitValue(IC_RIGHT(ic)) != 1)
13351         return 0;
13352
13353     /* if the size of this greater than one then no
13354        saving */
13355     if (getSize(operandType(IC_RESULT(ic))) > 1)
13356         return 0;
13357
13358     /* otherwise we can save BIG */
13359     lbl = newiTempLabel(NULL);
13360     lbl1= newiTempLabel(NULL);
13361
13362     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13363     
13364     if (IS_AOP_PREG(IC_RESULT(ic))) {
13365         pic16_emitcode("dec","%s",
13366                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13367         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13368         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13369     } else {    
13370
13371
13372       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13373       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13374
13375       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13376       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13377
13378     }
13379     
13380     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13381     ifx->generated = 1;
13382     return 1;
13383 }
13384
13385 /*-----------------------------------------------------------------*/
13386 /* genReceive - generate code for a receive iCode                  */
13387 /*-----------------------------------------------------------------*/
13388 static void genReceive (iCode *ic)
13389 {    
13390
13391   FENTRY;
13392
13393 #if 0
13394   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13395         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13396 #endif
13397 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13398
13399   if (isOperandInFarSpace(IC_RESULT(ic))
13400       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13401           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13402
13403     int size = getSize(operandType(IC_RESULT(ic)));
13404     int offset =  pic16_fReturnSizePic - size;
13405
13406       assert( 0 );
13407       while (size--) {
13408         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13409                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13410                       offset++;
13411         }
13412
13413       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13414
13415       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13416       size = AOP_SIZE(IC_RESULT(ic));
13417       offset = 0;
13418       while (size--) {
13419         pic16_emitcode ("pop","acc");
13420         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13421       }
13422   } else {
13423     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13424     _G.accInUse++;
13425     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13426     _G.accInUse--;
13427
13428     /* set pseudo stack pointer to where it should be - dw*/
13429     GpsuedoStkPtr = ic->parmBytes;
13430
13431     /* setting GpsuedoStkPtr has side effects here: */
13432     assignResultValue(IC_RESULT(ic), 0);
13433   }
13434
13435   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13436 }
13437
13438 /*-----------------------------------------------------------------*/
13439 /* genDummyRead - generate code for dummy read of volatiles        */
13440 /*-----------------------------------------------------------------*/
13441 static void
13442 genDummyRead (iCode * ic)
13443 {
13444   pic16_emitcode ("; genDummyRead","");
13445   pic16_emitcode ("; not implemented","");
13446
13447   ic = ic;
13448 }
13449
13450 /*-----------------------------------------------------------------*/
13451 /* genpic16Code - generate code for pic16 based controllers        */
13452 /*-----------------------------------------------------------------*/
13453 /*
13454  * At this point, ralloc.c has gone through the iCode and attempted
13455  * to optimize in a way suitable for a PIC. Now we've got to generate
13456  * PIC instructions that correspond to the iCode.
13457  *
13458  * Once the instructions are generated, we'll pass through both the
13459  * peep hole optimizer and the pCode optimizer.
13460  *-----------------------------------------------------------------*/
13461
13462 void genpic16Code (iCode *lic)
13463 {
13464   iCode *ic;
13465   int cln = 0;
13466
13467     lineHead = lineCurr = NULL;
13468
13469     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13470     pic16_addpBlock(pb);
13471
13472 #if 0
13473     /* if debug information required */
13474     if (options.debug && currFunc) {
13475       if (currFunc) {
13476         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13477       }
13478     }
13479 #endif
13480
13481     for (ic = lic ; ic ; ic = ic->next ) {
13482
13483       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
13484       if ( cln != ic->lineno ) {
13485         if ( options.debug ) {
13486           debugFile->writeCLine (ic);
13487         }
13488         
13489         if(!options.noCcodeInAsm) {
13490           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13491               printCLine(ic->filename, ic->lineno)));
13492         }
13493
13494         cln = ic->lineno ;
13495       }
13496         
13497       if(options.iCodeInAsm) {
13498         char *l;
13499
13500           /* insert here code to print iCode as comment */
13501           l = Safe_strdup(printILine(ic));
13502           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13503       }
13504         
13505       /* if the result is marked as
13506        * spilt and rematerializable or code for
13507        * this has already been generated then
13508        * do nothing */
13509       if (resultRemat(ic) || ic->generated ) 
13510         continue ;
13511         
13512       /* depending on the operation */
13513       switch (ic->op) {
13514         case '!' :
13515           pic16_genNot(ic);
13516           break;
13517             
13518         case '~' :
13519           pic16_genCpl(ic);
13520           break;
13521             
13522         case UNARYMINUS:
13523           genUminus (ic);
13524           break;
13525             
13526         case IPUSH:
13527           genIpush (ic);
13528           break;
13529             
13530         case IPOP:
13531           /* IPOP happens only when trying to restore a 
13532            * spilt live range, if there is an ifx statement
13533            * following this pop then the if statement might
13534            * be using some of the registers being popped which
13535            * would destroy the contents of the register so
13536            * we need to check for this condition and handle it */
13537            if (ic->next
13538              && ic->next->op == IFX
13539              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13540                genIfx (ic->next,ic);
13541           else
13542             genIpop (ic);
13543           break; 
13544             
13545         case CALL:
13546           genCall (ic);
13547           break;
13548             
13549         case PCALL:
13550           genPcall (ic);
13551           break;
13552             
13553         case FUNCTION:
13554           genFunction (ic);
13555           break;
13556             
13557         case ENDFUNCTION:
13558           genEndFunction (ic);
13559           break;
13560             
13561         case RETURN:
13562           genRet (ic);
13563           break;
13564             
13565         case LABEL:
13566           genLabel (ic);
13567           break;
13568             
13569         case GOTO:
13570           genGoto (ic);
13571           break;
13572             
13573         case '+' :
13574           pic16_genPlus (ic) ;
13575           break;
13576             
13577         case '-' :
13578           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13579             pic16_genMinus (ic);
13580           break;
13581
13582         case '*' :
13583           genMult (ic);
13584           break;
13585             
13586         case '/' :
13587           genDiv (ic) ;
13588           break;
13589             
13590         case '%' :
13591           genMod (ic);
13592           break;
13593             
13594         case '>' :
13595           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13596           break;
13597             
13598         case '<' :
13599           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13600           break;
13601             
13602         case LE_OP:
13603         case GE_OP:
13604         case NE_OP:
13605           /* note these two are xlated by algebraic equivalence
13606            * during parsing SDCC.y */
13607           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13608             "got '>=' or '<=' shouldn't have come here");
13609           break;
13610
13611         case EQ_OP:
13612           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13613           break;            
13614             
13615         case AND_OP:
13616           genAndOp (ic);
13617           break;
13618             
13619         case OR_OP:
13620           genOrOp (ic);
13621           break;
13622             
13623         case '^' :
13624           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13625           break;
13626             
13627         case '|' :
13628           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13629           break;
13630             
13631         case BITWISEAND:
13632           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13633           break;
13634             
13635         case INLINEASM:
13636           genInline (ic);
13637           break;
13638             
13639         case RRC:
13640           genRRC (ic);
13641           break;
13642             
13643         case RLC:
13644           genRLC (ic);
13645           break;
13646             
13647         case GETHBIT:
13648           genGetHbit (ic);
13649           break;
13650             
13651         case LEFT_OP:
13652           genLeftShift (ic);
13653           break;
13654             
13655         case RIGHT_OP:
13656           genRightShift (ic);
13657           break;
13658             
13659         case GET_VALUE_AT_ADDRESS:
13660           genPointerGet(ic);
13661           break;
13662             
13663         case '=' :
13664           if (POINTER_SET(ic))
13665             genPointerSet(ic);
13666           else
13667             genAssign(ic);
13668           break;
13669             
13670         case IFX:
13671           genIfx (ic,NULL);
13672           break;
13673             
13674         case ADDRESS_OF:
13675           genAddrOf (ic);
13676           break;
13677             
13678         case JUMPTABLE:
13679           genJumpTab (ic);
13680           break;
13681             
13682         case CAST:
13683           genCast (ic);
13684           break;
13685             
13686         case RECEIVE:
13687           genReceive(ic);
13688           break;
13689             
13690         case SEND:
13691           addSet(&_G.sendSet,ic);
13692           break;
13693
13694         case DUMMY_READ_VOLATILE:
13695           genDummyRead (ic);
13696           break;
13697
13698         default :
13699           ic = ic;
13700       }
13701     }
13702
13703
13704     /* now we are ready to call the
13705        peep hole optimizer */
13706     if (!options.nopeep)
13707       peepHole (&lineHead);
13708
13709     /* now do the actual printing */
13710     printLine (lineHead, codeOutFile);
13711
13712 #ifdef PCODE_DEBUG
13713     DFPRINTF((stderr,"printing pBlock\n\n"));
13714     pic16_printpBlock(stdout,pb);
13715 #endif
13716
13717     return;
13718 }
13719