* src/SDCCglobl.h: ensure that PATH_MAX >= 2048 to guarantee
[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_frame_plusw ), 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     /* This is a bit too restrictive if one is a subset of the other...
1073     if (aop1->size != aop2->size )
1074         return FALSE ;
1075     */
1076
1077     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1078 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1079
1080 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1081         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1082             return FALSE ;
1083     }
1084
1085     return TRUE ;
1086 }
1087
1088 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1089 {
1090     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1091                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1092
1093     if(aop1 == aop2)return TRUE;
1094     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1095       
1096       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1097     
1098   return TRUE;
1099 }
1100
1101
1102 /*-----------------------------------------------------------------*/
1103 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1104 /*-----------------------------------------------------------------*/
1105 void pic16_aopOp (operand *op, iCode *ic, bool result)
1106 {
1107     asmop *aop;
1108     symbol *sym;
1109     int i;
1110
1111     if (!op)
1112         return ;
1113
1114     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1115
1116     /* if this a literal */
1117     if (IS_OP_LITERAL(op)) {
1118         op->aop = aop = newAsmop(AOP_LIT);
1119         aop->aopu.aop_lit = op->operand.valOperand;
1120         aop->size = getSize(operandType(op));
1121         return;
1122     }
1123
1124     {
1125       sym_link *type = operandType(op);
1126 #if 0
1127       if(IS_PTR_CONST(type))
1128 #else
1129       if(IS_CODEPTR(type))
1130 #endif
1131         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1132     }
1133
1134     /* if already has a asmop then continue */
1135     if (op->aop)
1136         return ;
1137
1138     /* if the underlying symbol has a aop */
1139     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1140       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1141         op->aop = OP_SYMBOL(op)->aop;
1142         return;
1143     }
1144
1145     /* if this is a true symbol */
1146     if (IS_TRUE_SYMOP(op)) {    
1147         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1148       op->aop = aopForSym(ic, op, result);
1149       return ;
1150     }
1151
1152     /* this is a temporary : this has
1153     only four choices :
1154     a) register
1155     b) spillocation
1156     c) rematerialize 
1157     d) conditional   
1158     e) can be a return use only */
1159
1160     sym = OP_SYMBOL(op);
1161
1162     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1163     /* if the type is a conditional */
1164     if (sym->regType == REG_CND) {
1165         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1166         aop->size = 0;
1167         return;
1168     }
1169
1170     /* if it is spilt then two situations
1171     a) is rematerialize 
1172     b) has a spill location */
1173     if (sym->isspilt || sym->nRegs == 0) {
1174
1175       DEBUGpic16_emitcode(";","%d",__LINE__);
1176         /* rematerialize it NOW */
1177         if (sym->remat) {
1178
1179             sym->aop = op->aop = aop = aopForRemat (op);
1180 //            aop->size = getSize(sym->type);
1181 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1182             return;
1183         }
1184
1185 #if 1
1186         if (sym->accuse) {
1187             int i;
1188             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1189             aop->size = getSize(sym->type);
1190             for ( i = 0 ; i < 1 ; i++ ) {
1191                 aop->aopu.aop_str[i] = accUse[i];
1192 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1193             }
1194             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1195             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1196             return;  
1197         }
1198 #endif
1199
1200 #if 1
1201         if (sym->ruonly ) {
1202           /*
1203           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1204           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1205           //pic16_allocDirReg (IC_LEFT(ic));
1206           aop->size = getSize(sym->type);
1207           */
1208
1209           unsigned i;
1210
1211           aop = op->aop = sym->aop = newAsmop(AOP_STR);
1212           aop->size = getSize(sym->type);
1213           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1214             aop->aopu.aop_str[i] = fReturn[i];
1215
1216           DEBUGpic16_emitcode(";","%d",__LINE__);
1217           return;
1218         }
1219 #endif
1220         /* else spill location  */
1221         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1222             /* force a new aop if sizes differ */
1223             sym->usl.spillLoc->aop = NULL;
1224         }
1225
1226 #if 0
1227         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1228                             __FUNCTION__,__LINE__,
1229                             sym->usl.spillLoc->rname,
1230                             sym->rname, sym->usl.spillLoc->offset);
1231 #endif
1232
1233         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1234         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1235         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1236                                           getSize(sym->type), 
1237                                           sym->usl.spillLoc->offset, op);
1238         aop->size = getSize(sym->type);
1239
1240         return;
1241     }
1242
1243     {
1244       sym_link *type = operandType(op);
1245 #if 0
1246       if(IS_PTR_CONST(type)) 
1247 #else
1248       if(IS_CODEPTR(type)) 
1249 #endif
1250         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1251     }
1252
1253     /* must be in a register */
1254     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1255     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1256     aop->size = sym->nRegs;
1257     for ( i = 0 ; i < sym->nRegs ;i++)
1258         aop->aopu.aop_reg[i] = sym->regs[i];
1259 }
1260
1261 /*-----------------------------------------------------------------*/
1262 /* pic16_freeAsmop - free up the asmop given to an operand               */
1263 /*----------------------------------------------------------------*/
1264 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1265 {   
1266     asmop *aop ;
1267
1268     if (!op)
1269         aop = aaop;
1270     else 
1271         aop = op->aop;
1272
1273     if (!aop)
1274         return ;
1275
1276     if (aop->freed)
1277         goto dealloc; 
1278
1279     aop->freed = 1;
1280
1281     /* depending on the asmop type only three cases need work AOP_RO
1282        , AOP_R1 && AOP_STK */
1283 #if 1
1284     switch (aop->type) {
1285         case AOP_FSR0 :
1286             if (_G.fsr0Pushed ) {
1287                 if (pop) {
1288                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1289                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1290 //                    pic16_emitcode ("pop","ar0");
1291                     _G.fsr0Pushed--;
1292                 }
1293             }
1294             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1295             break;
1296
1297         case AOP_FSR2 :
1298             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1299             break;
1300
1301         case AOP_R0 :
1302             if (_G.r0Pushed ) {
1303                 if (pop) {
1304                     pic16_emitcode ("pop","ar0");     
1305                     _G.r0Pushed--;
1306                 }
1307             }
1308             bitVectUnSetBit(ic->rUsed,R0_IDX);
1309             break;
1310
1311         case AOP_R1 :
1312             if (_G.r1Pushed ) {
1313                 if (pop) {
1314                     pic16_emitcode ("pop","ar1");
1315                     _G.r1Pushed--;
1316                 }
1317             }
1318             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1319             break;
1320
1321         case AOP_STA:
1322           {
1323             int i;
1324
1325               /* we must store the result on stack */
1326               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1327                 // operands on stack are accessible via "FSR2 + index" with index
1328                 // starting at 2 for arguments and growing from 0 downwards for
1329                 // local variables (index == 0 is not assigned so we add one here)
1330                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1331                 if (soffs <= 0) {
1332                   assert (soffs < 0);
1333                   soffs++;
1334                 } // if
1335                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1336                 for(i=0;i<aop->size;i++) {
1337                   /* initialise for stack access via frame pointer */
1338                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1339                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1340                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1341                 }
1342         
1343                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1344               }
1345
1346               if(!_G.resDirect) {
1347                 for(i=0;i<aop->size;i++)
1348                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1349               }
1350               _G.resDirect = 0;
1351           }
1352           break;
1353 #if 0
1354         case AOP_STK :
1355         {
1356             int sz = aop->size;    
1357             int stk = aop->aopu.aop_stk + aop->size;
1358             bitVectUnSetBit(ic->rUsed,R0_IDX);
1359             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1360
1361             getFreePtr(ic,&aop,FALSE);
1362             
1363             if (options.stack10bit)
1364             {
1365                 /* I'm not sure what to do here yet... */
1366                 /* #STUB */
1367                 fprintf(stderr, 
1368                         "*** Warning: probably generating bad code for "
1369                         "10 bit stack mode.\n");
1370             }
1371             
1372             if (stk) {
1373                 pic16_emitcode ("mov","a,_bp");
1374                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1375                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1376             } else {
1377                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1378             }
1379
1380             while (sz--) {
1381                 pic16_emitcode("pop","acc");
1382                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1383                 if (!sz) break;
1384                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1385             }
1386             op->aop = aop;
1387             pic16_freeAsmop(op,NULL,ic,TRUE);
1388             if (_G.r0Pushed) {
1389                 pic16_emitcode("pop","ar0");
1390                 _G.r0Pushed--;
1391             }
1392
1393             if (_G.r1Pushed) {
1394                 pic16_emitcode("pop","ar1");
1395                 _G.r1Pushed--;
1396             }       
1397         }
1398 #endif
1399
1400     }
1401 #endif
1402
1403 dealloc:
1404     /* all other cases just dealloc */
1405     if (op ) {
1406         op->aop = NULL;
1407         if (IS_SYMOP(op)) {
1408             OP_SYMBOL(op)->aop = NULL;    
1409             /* if the symbol has a spill */
1410             if (SPIL_LOC(op))
1411                 SPIL_LOC(op)->aop = NULL;
1412         }
1413     }
1414 }
1415
1416 /*-----------------------------------------------------------------*/
1417 /* pic16_aopGet - for fetching value of the aop                          */
1418 /*-----------------------------------------------------------------*/
1419 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1420 {
1421     char *s = buffer ;
1422     char *rs;
1423
1424     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1425
1426     /* offset is greater than size then zero */
1427     if (offset > (aop->size - 1) &&
1428         aop->type != AOP_LIT)
1429         return zero;
1430
1431     /* depending on type */
1432     switch (aop->type) {
1433
1434     case AOP_FSR0:
1435     case AOP_FSR2:
1436       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1437       rs = Safe_calloc(1, strlen(s)+1);
1438       strcpy(rs, s);
1439       return (rs);
1440       
1441 #if 0
1442       /* if we need to increment it */
1443       while (offset > aop->coff)
1444         {
1445           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1446           aop->coff++;
1447         }
1448
1449       while (offset < aop->coff)
1450         {
1451           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1452           aop->coff--;
1453         }
1454       aop->coff = offset;
1455       if (aop->paged)
1456         {
1457           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1458           return (dname ? "acc" : "a");
1459         }
1460       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1461       rs = Safe_calloc (1, strlen (s) + 1);
1462       strcpy (rs, s);
1463       return rs;
1464 #endif
1465
1466         
1467     case AOP_IMMD:
1468         if (bit16) 
1469             sprintf (s,"%s",aop->aopu.aop_immd);
1470         else
1471             if (offset) 
1472                 sprintf(s,"(%s >> %d)",
1473                         aop->aopu.aop_immd,
1474                         offset*8);
1475             else
1476                 sprintf(s,"%s",
1477                         aop->aopu.aop_immd);
1478         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1479         rs = Safe_calloc(1,strlen(s)+1);
1480         strcpy(rs,s);   
1481         return rs;
1482         
1483     case AOP_DIR:
1484       if (offset) {
1485         sprintf(s,"(%s + %d)",
1486                 aop->aopu.aop_dir,
1487                 offset);
1488         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1489       } else
1490             sprintf(s,"%s",aop->aopu.aop_dir);
1491         rs = Safe_calloc(1,strlen(s)+1);
1492         strcpy(rs,s);   
1493         return rs;
1494         
1495     case AOP_REG:
1496       //if (dname) 
1497       //    return aop->aopu.aop_reg[offset]->dname;
1498       //else
1499             return aop->aopu.aop_reg[offset]->name;
1500         
1501     case AOP_CRY:
1502       //pic16_emitcode(";","%d",__LINE__);
1503       return aop->aopu.aop_dir;
1504         
1505     case AOP_ACC:
1506         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1507 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1508 //        assert( 0 );
1509 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1510         rs = Safe_strdup("WREG");
1511         return (rs);
1512
1513     case AOP_LIT:
1514         sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1515         rs = Safe_calloc(1,strlen(s)+1);
1516         strcpy(rs,s);   
1517         return rs;
1518         
1519     case AOP_STR:
1520         aop->coff = offset ;
1521         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1522             dname)
1523             return "acc";
1524         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1525         
1526         return aop->aopu.aop_str[offset];
1527         
1528     case AOP_PCODE:
1529       {
1530         pCodeOp *pcop = aop->aopu.pcop;
1531         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1532         if(pcop->name) {
1533           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1534           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1535           if (offset) {
1536             sprintf(s,"(%s + %d)", pcop->name, offset);
1537           } else {
1538             sprintf(s,"%s", pcop->name);
1539           }
1540         } else
1541           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1542
1543       }
1544       rs = Safe_calloc(1,strlen(s)+1);
1545       strcpy(rs,s);   
1546       return rs;
1547
1548     case AOP_STA:
1549         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1550         return (rs);
1551         
1552     case AOP_STK:
1553 //        pCodeOp *pcop = aop->aop
1554         break;
1555
1556     }
1557
1558     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1559     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1560            "aopget got unsupported aop->type");
1561     exit(0);
1562 }
1563
1564
1565
1566 /* lock has the following meaning: When allocating temporary registers
1567  * for stack variables storage, the value of the temporary register is
1568  * saved on stack. Its value is restored at the end. This procedure is
1569  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1570  * a possibility that before a call to pic16_aopOp, a temporary register
1571  * is allocated for a while and it is freed after some time, this will
1572  * mess the stack and values will not be restored properly. So use lock=1
1573  * to allocate temporary registers used internally by the programmer, and
1574  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1575  * to inform the compiler developer about a possible bug. This is an internal
1576  * feature for developing the compiler -- VR */
1577  
1578 int _TempReg_lock = 0;
1579 /*-----------------------------------------------------------------*/
1580 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1581 /*-----------------------------------------------------------------*/
1582 pCodeOp *pic16_popGetTempReg(int lock)
1583 {
1584   pCodeOp *pcop;
1585   symbol *cfunc;
1586
1587 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1588     if(_TempReg_lock) {
1589 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1590     }
1591     
1592     _TempReg_lock += lock;
1593     
1594     cfunc = currFunc;
1595     currFunc = NULL;
1596
1597     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1598     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1599       PCOR(pcop)->r->wasUsed=1;
1600       PCOR(pcop)->r->isFree=0;
1601
1602       /* push value on stack */
1603       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1604     }
1605
1606     currFunc = cfunc;
1607
1608   return pcop;
1609 }
1610
1611 /*-----------------------------------------------------------------*/
1612 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but   */
1613 /*                            don't save if inside v               */
1614 /*-----------------------------------------------------------------*/
1615 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1616 {
1617   pCodeOp *pcop;
1618   symbol *cfunc;
1619
1620 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1621
1622     if(_TempReg_lock) {
1623 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1624     }
1625
1626     _TempReg_lock += lock;
1627
1628     cfunc = currFunc;
1629     currFunc = NULL;
1630
1631     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1632     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1633       PCOR(pcop)->r->wasUsed=1;
1634       PCOR(pcop)->r->isFree=0;
1635
1636       if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1637       /* push value on stack */
1638         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1639       }
1640     }
1641
1642     currFunc = cfunc;
1643
1644   return pcop;
1645 }
1646
1647
1648 /*-----------------------------------------------------------------*/
1649 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1650 /*-----------------------------------------------------------------*/
1651 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1652 {
1653   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1654
1655   _TempReg_lock -= lock;
1656
1657   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1658     PCOR(pcop)->r->isFree = 1;
1659     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1660   }
1661 }
1662 /*-----------------------------------------------------------------*/
1663 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1664 /*-----------------------------------------------------------------*/
1665 pCodeOp *pic16_popGetLabel(unsigned int key)
1666 {
1667
1668   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1669
1670   if(key>max_key)
1671     max_key = key;
1672
1673   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1674 }
1675
1676 /*-----------------------------------------------------------------*/
1677 /* pic16_popCopyReg - copy a pcode operator                              */
1678 /*-----------------------------------------------------------------*/
1679 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1680 {
1681   pCodeOpReg *pcor;
1682
1683   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1684   pcor->pcop.type = pc->pcop.type;
1685   if(pc->pcop.name) {
1686     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1687       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1688   } else
1689     pcor->pcop.name = NULL;
1690
1691   pcor->r = pc->r;
1692   pcor->rIdx = pc->rIdx;
1693   pcor->r->wasUsed=1;
1694   pcor->instance = pc->instance;
1695
1696 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1697
1698   return PCOP(pcor);
1699 }
1700
1701 /*-----------------------------------------------------------------*/
1702 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1703 /*-----------------------------------------------------------------*/
1704 pCodeOp *pic16_popGetLit(int lit)
1705 {
1706   return pic16_newpCodeOpLit(lit);
1707 }
1708
1709 /*-----------------------------------------------------------------*/
1710 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1711 /*-----------------------------------------------------------------*/
1712 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1713 {
1714   return pic16_newpCodeOpLit2(lit, arg2);
1715 }
1716
1717
1718 /*-----------------------------------------------------------------*/
1719 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1720 /*-----------------------------------------------------------------*/
1721 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1722 {
1723   return pic16_newpCodeOpImmd(name, offset,index, 0);
1724 }
1725
1726
1727 /*-----------------------------------------------------------------*/
1728 /* pic16_popGet - asm operator to pcode operator conversion              */
1729 /*-----------------------------------------------------------------*/
1730 pCodeOp *pic16_popGetWithString(char *str)
1731 {
1732   pCodeOp *pcop;
1733
1734
1735   if(!str) {
1736     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1737     exit (1);
1738   }
1739
1740   pcop = pic16_newpCodeOp(str,PO_STR);
1741
1742   return pcop;
1743 }
1744
1745 /*-----------------------------------------------------------------*/
1746 /* pic16_popRegFromString -                                        */
1747 /*-----------------------------------------------------------------*/
1748 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1749 {
1750
1751   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1752   pcop->type = PO_DIR;
1753
1754   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1755   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1756
1757   if(!str)
1758     str = "BAD_STRING";
1759
1760   pcop->name = Safe_calloc(1,strlen(str)+1);
1761   strcpy(pcop->name,str);
1762
1763   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1764
1765   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1766
1767   /* make sure that register doesn't exist,
1768    * and operand isn't NULL
1769    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1770   if((PCOR(pcop)->r == NULL) 
1771     && (op)
1772     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1773 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1774 //              __FUNCTION__, __LINE__, str, size, offset);
1775
1776     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1777     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1778
1779   }
1780   PCOR(pcop)->instance = offset;
1781
1782   return pcop;
1783 }
1784
1785 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1786 {
1787   pCodeOp *pcop;
1788
1789 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1790
1791         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1792         PCOR(pcop)->rIdx = rIdx;
1793         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1794
1795         PCOR(pcop)->r->isFree = 0;
1796         PCOR(pcop)->r->wasUsed = 1;
1797
1798         pcop->type = PCOR(pcop)->r->pc_type;
1799
1800   return pcop;
1801 }
1802
1803 /*---------------------------------------------------------------------------------*/
1804 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1805 /*                 VR 030601                                                       */
1806 /*---------------------------------------------------------------------------------*/
1807 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1808 {
1809   pCodeOpReg2 *pcop2;
1810   pCodeOp *temp;
1811   
1812         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1813
1814         /* comment the following check, so errors to throw up */
1815 //      if(!pcop2)return NULL;
1816
1817         temp = pic16_popGet(aop_dst, offset);
1818         pcop2->pcop2 = temp;
1819         
1820   return PCOP(pcop2);
1821 }
1822
1823
1824
1825 /*--------------------------------------------------------------------------------.-*/
1826 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1827 /*                  VR 030601 , adapted by Hans Dorn                                */
1828 /*--------------------------------------------------------------------------------.-*/
1829 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1830 {
1831   pCodeOpReg2 *pcop2;
1832  
1833         pcop2 = (pCodeOpReg2 *)src;
1834         pcop2->pcop2 = dst;
1835         
1836         return PCOP(pcop2);
1837 }
1838
1839
1840
1841 /*---------------------------------------------------------------------------------*/
1842 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1843 /*                     movff instruction                                           */
1844 /*---------------------------------------------------------------------------------*/
1845 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1846 {
1847   pCodeOpReg2 *pcop2;
1848
1849         if(!noalloc) {
1850                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1851                 pcop2->pcop2 = pic16_popCopyReg(dst);
1852         } else {
1853                 /* the pCodeOp may be already allocated */
1854                 pcop2 = (pCodeOpReg2 *)(src);
1855                 pcop2->pcop2 = (pCodeOp *)(dst);
1856         }
1857
1858   return PCOP(pcop2);
1859 }
1860
1861
1862 /*-----------------------------------------------------------------*/
1863 /* pic16_popGet - asm operator to pcode operator conversion              */
1864 /*-----------------------------------------------------------------*/
1865 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1866 {
1867   //char *s = buffer ;
1868   char *rs;
1869   pCodeOp *pcop;
1870
1871     FENTRY2;
1872     /* offset is greater than
1873     size then zero */
1874
1875 //    if (offset > (aop->size - 1) &&
1876 //        aop->type != AOP_LIT)
1877 //      return NULL;  //zero;
1878
1879     /* depending on type */
1880     switch (aop->type) {
1881         
1882     case AOP_R0:
1883     case AOP_R1:
1884     case AOP_DPTR:
1885     case AOP_DPTR2:
1886         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1887         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1888         assert( 0 );
1889         return NULL;
1890
1891
1892     case AOP_FSR0:
1893     case AOP_FSR2:
1894       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1895       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
1896       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1897       PCOR(pcop)->r->wasUsed = 1;
1898       PCOR(pcop)->r->isFree = 0;
1899       
1900       PCOR(pcop)->instance = offset;
1901       pcop->type = PCOR(pcop)->r->pc_type;
1902       return (pcop);
1903
1904     case AOP_IMMD:
1905       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1906       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1907
1908     case AOP_STA:
1909       /* pCodeOp is already allocated from aopForSym */
1910         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1911         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1912           
1913       return (pcop);
1914       
1915     case AOP_ACC:
1916       {
1917         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1918
1919         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1920
1921         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1922         
1923         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1924         PCOR(pcop)->rIdx = rIdx;
1925         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1926         PCOR(pcop)->r->wasUsed=1;
1927         PCOR(pcop)->r->isFree=0;
1928
1929         PCOR(pcop)->instance = offset;
1930         pcop->type = PCOR(pcop)->r->pc_type;
1931 //      rs = aop->aopu.aop_reg[offset]->name;
1932 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1933         return pcop;
1934
1935
1936 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1937 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1938
1939 //      assert( 0 );
1940       }
1941         
1942     case AOP_DIR:
1943       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1944       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1945         
1946     case AOP_REG:
1947       {
1948         int rIdx;
1949         assert (aop && aop->aopu.aop_reg[offset] != NULL);
1950         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1951
1952         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1953         
1954         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1955 //      pcop->type = PO_GPR_REGISTER;
1956         PCOR(pcop)->rIdx = rIdx;
1957         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
1958         PCOR(pcop)->r->wasUsed=1;
1959         PCOR(pcop)->r->isFree=0;
1960
1961         PCOR(pcop)->instance = offset;
1962         pcop->type = PCOR(pcop)->r->pc_type;
1963         
1964         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s\n", __LINE__, dumpPicOptype(pcop->type));
1965         rs = aop->aopu.aop_reg[offset]->name;
1966         DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
1967         return pcop;
1968       }
1969
1970     case AOP_CRY:
1971         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1972
1973       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1974       PCOR(pcop)->instance = offset;
1975       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1976       //if(PCOR(pcop)->r == NULL)
1977       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1978       return pcop;
1979         
1980     case AOP_LIT:
1981         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1982       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1983
1984     case AOP_STR:
1985       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1986       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1987
1988       /*
1989       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1990       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1991       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1992       pcop->type = PCOR(pcop)->r->pc_type;
1993       pcop->name = PCOR(pcop)->r->name;
1994
1995       return pcop;
1996       */
1997
1998     case AOP_PCODE:
1999       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2000                           __LINE__, 
2001                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2002       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2003       switch( aop->aopu.pcop->type ) {
2004         case PO_DIR: PCOR(pcop)->instance += offset; break;
2005         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2006         default:
2007           assert( 0 );  /* should never reach here */;
2008       }
2009       return pcop;
2010     }
2011
2012     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2013            "pic16_popGet got unsupported aop->type");
2014     exit(0);
2015 }
2016 /*-----------------------------------------------------------------*/
2017 /* pic16_aopPut - puts a string for a aop                                */
2018 /*-----------------------------------------------------------------*/
2019 void pic16_aopPut (asmop *aop, char *s, int offset)
2020 {
2021     char *d = buffer ;
2022     symbol *lbl ;
2023
2024     return;
2025
2026     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2027
2028     if (aop->size && offset > ( aop->size - 1)) {
2029         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2030                "pic16_aopPut got offset > aop->size");
2031         exit(0);
2032     }
2033
2034     /* will assign value to value */
2035     /* depending on where it is ofcourse */
2036     switch (aop->type) {
2037     case AOP_DIR:
2038       if (offset) {
2039         sprintf(d,"(%s + %d)",
2040                 aop->aopu.aop_dir,offset);
2041         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2042
2043       } else
2044             sprintf(d,"%s",aop->aopu.aop_dir);
2045         
2046         if (strcmp(d,s)) {
2047           DEBUGpic16_emitcode(";","%d",__LINE__);
2048           if(strcmp(s,"W"))
2049             pic16_emitcode("movf","%s,w",s);
2050           pic16_emitcode("movwf","%s",d);
2051
2052           if(strcmp(s,"W")) {
2053             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2054             if(offset >= aop->size) {
2055               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2056               break;
2057             } else
2058               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2059           }
2060
2061           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2062
2063
2064         }
2065         break;
2066         
2067     case AOP_REG:
2068       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2069         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2070           /*
2071             if (*s == '@'           ||
2072                 strcmp(s,"r0") == 0 ||
2073                 strcmp(s,"r1") == 0 ||
2074                 strcmp(s,"r2") == 0 ||
2075                 strcmp(s,"r3") == 0 ||
2076                 strcmp(s,"r4") == 0 ||
2077                 strcmp(s,"r5") == 0 ||
2078                 strcmp(s,"r6") == 0 || 
2079                 strcmp(s,"r7") == 0 )
2080                 pic16_emitcode("mov","%s,%s  ; %d",
2081                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2082             else
2083           */
2084
2085           if(strcmp(s,"W")==0 )
2086             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2087
2088           pic16_emitcode("movwf","%s",
2089                    aop->aopu.aop_reg[offset]->name);
2090
2091           if(strcmp(s,zero)==0) {
2092             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2093
2094           } else if(strcmp(s,"W")==0) {
2095             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2096             pcop->type = PO_GPR_REGISTER;
2097
2098             PCOR(pcop)->rIdx = -1;
2099             PCOR(pcop)->r = NULL;
2100
2101             DEBUGpic16_emitcode(";","%d",__LINE__);
2102             pcop->name = Safe_strdup(s);
2103             pic16_emitpcode(POC_MOVFW,pcop);
2104             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2105           } else if(strcmp(s,one)==0) {
2106             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2107             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2108           } else {
2109             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2110           }
2111         }
2112         break;
2113         
2114     case AOP_DPTR:
2115     case AOP_DPTR2:
2116     
2117     if (aop->type == AOP_DPTR2)
2118     {
2119         genSetDPTR(1);
2120     }
2121     
2122         if (aop->code) {
2123             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2124                    "pic16_aopPut writting to code space");
2125             exit(0);
2126         }
2127         
2128         while (offset > aop->coff) {
2129             aop->coff++;
2130             pic16_emitcode ("inc","dptr");
2131         }
2132         
2133         while (offset < aop->coff) {
2134             aop->coff-- ;
2135             pic16_emitcode("lcall","__decdptr");
2136         }
2137         
2138         aop->coff = offset;
2139         
2140         /* if not in accumulater */
2141         MOVA(s);        
2142         
2143         pic16_emitcode ("movx","@dptr,a");
2144         
2145     if (aop->type == AOP_DPTR2)
2146     {
2147         genSetDPTR(0);
2148     }
2149         break;
2150         
2151     case AOP_R0:
2152     case AOP_R1:
2153         while (offset > aop->coff) {
2154             aop->coff++;
2155             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2156         }
2157         while (offset < aop->coff) {
2158             aop->coff-- ;
2159             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2160         }
2161         aop->coff = offset;
2162         
2163         if (aop->paged) {
2164             MOVA(s);           
2165             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2166             
2167         } else
2168             if (*s == '@') {
2169                 MOVA(s);
2170                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2171             } else
2172                 if (strcmp(s,"r0") == 0 ||
2173                     strcmp(s,"r1") == 0 ||
2174                     strcmp(s,"r2") == 0 ||
2175                     strcmp(s,"r3") == 0 ||
2176                     strcmp(s,"r4") == 0 ||
2177                     strcmp(s,"r5") == 0 ||
2178                     strcmp(s,"r6") == 0 || 
2179                     strcmp(s,"r7") == 0 ) {
2180                     char buffer[10];
2181                     sprintf(buffer,"a%s",s);
2182                     pic16_emitcode("mov","@%s,%s",
2183                              aop->aopu.aop_ptr->name,buffer);
2184                 } else
2185                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2186         
2187         break;
2188         
2189     case AOP_STK:
2190         if (strcmp(s,"a") == 0)
2191             pic16_emitcode("push","acc");
2192         else
2193             pic16_emitcode("push","%s",s);
2194         
2195         break;
2196         
2197     case AOP_CRY:
2198         /* if bit variable */
2199         if (!aop->aopu.aop_dir) {
2200             pic16_emitcode("clr","a");
2201             pic16_emitcode("rlc","a");
2202         } else {
2203             if (s == zero) 
2204                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2205             else
2206                 if (s == one)
2207                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2208                 else
2209                     if (!strcmp(s,"c"))
2210                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2211                     else {
2212                         lbl = newiTempLabel(NULL);
2213                         
2214                         if (strcmp(s,"a")) {
2215                             MOVA(s);
2216                         }
2217                         pic16_emitcode("clr","c");
2218                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2219                         pic16_emitcode("cpl","c");
2220                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2221                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2222                     }
2223         }
2224         break;
2225         
2226     case AOP_STR:
2227         aop->coff = offset;
2228         if (strcmp(aop->aopu.aop_str[offset],s))
2229             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2230         break;
2231         
2232     case AOP_ACC:
2233         aop->coff = offset;
2234         if (!offset && (strcmp(s,"acc") == 0))
2235             break;
2236         
2237         if (strcmp(aop->aopu.aop_str[offset],s))
2238             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2239         break;
2240
2241     default :
2242         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2243 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2244 //             "pic16_aopPut got unsupported aop->type");
2245 //      exit(0);    
2246     }    
2247
2248 }
2249
2250 /*-----------------------------------------------------------------*/
2251 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2252 /*-----------------------------------------------------------------*/
2253 void pic16_mov2w (asmop *aop, int offset)
2254 {
2255   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2256
2257   if(is_LitAOp(aop))
2258     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2259   else
2260     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2261 }
2262
2263 static void mov2f(asmop *dst, asmop *src, int offset)
2264 {
2265   if(is_LitAOp(src)) {
2266     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2267     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2268   } else {
2269     if(pic16_sameRegsOfs(src, dst, offset))return;
2270     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2271                       pic16_popGet(dst, offset)));
2272   }
2273 }
2274
2275 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2276 {
2277   if(is_LitAOp(src)) {
2278     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2279     pic16_emitpcode(POC_MOVWF, dst);
2280   } else {
2281     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2282   }
2283 }
2284
2285 void pic16_testStackOverflow(void)
2286 {
2287 #define GSTACK_TEST_NAME        "__gstack_test"
2288
2289   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2290   
2291   {
2292     symbol *sym;
2293
2294       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2295       strcpy(sym->rname, GSTACK_TEST_NAME);
2296       checkAddSym(&externs, sym);
2297   }
2298
2299 }
2300
2301 /* push pcop into stack */
2302 void pic16_pushpCodeOp(pCodeOp *pcop)
2303 {
2304 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2305   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));    //&pic16_pc_postdec1)));
2306   if(pic16_options.gstack)
2307     pic16_testStackOverflow();
2308     
2309 }
2310
2311 /* pop pcop from stack */
2312 void pic16_poppCodeOp(pCodeOp *pcop)
2313 {
2314   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2315   if(pic16_options.gstack)
2316     pic16_testStackOverflow();
2317 }
2318
2319
2320 /*-----------------------------------------------------------------*/
2321 /* pushw - pushes wreg to stack                                    */
2322 /*-----------------------------------------------------------------*/
2323 void pushw(void)
2324 {
2325   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2326   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));  //&pic16_pc_postdec1));
2327   if(pic16_options.gstack)
2328     pic16_testStackOverflow();
2329 }
2330
2331                 
2332 /*-----------------------------------------------------------------*/
2333 /* pushaop - pushes aop to stack                                   */
2334 /*-----------------------------------------------------------------*/
2335 void pushaop(asmop *aop, int offset)
2336 {
2337   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2338
2339   if(is_LitAOp(aop)) {
2340     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2341     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));        //&pic16_pc_postdec1));
2342   } else {
2343     pic16_emitpcode(POC_MOVFF,
2344       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));      //&pic16_pc_postdec1)));
2345   }
2346
2347   if(pic16_options.gstack)
2348     pic16_testStackOverflow();
2349 }
2350
2351 /*-----------------------------------------------------------------*/
2352 /* popaop - pops aop from stack                                    */
2353 /*-----------------------------------------------------------------*/
2354 void popaop(asmop *aop, int offset)
2355 {
2356   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2357   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2358   if(pic16_options.gstack)
2359     pic16_testStackOverflow();
2360 }
2361
2362 void popaopidx(asmop *aop, int offset, int index)
2363 {
2364   int ofs=1;
2365
2366     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2367
2368     if(STACK_MODEL_LARGE)ofs++;
2369
2370     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2371     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2372     if(pic16_options.gstack)
2373       pic16_testStackOverflow();
2374 }
2375
2376 #if !(USE_GENERIC_SIGNED_SHIFT)
2377 /*-----------------------------------------------------------------*/
2378 /* reAdjustPreg - points a register back to where it should        */
2379 /*-----------------------------------------------------------------*/
2380 static void reAdjustPreg (asmop *aop)
2381 {
2382     int size ;
2383
2384     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2385     aop->coff = 0;
2386     if ((size = aop->size) <= 1)
2387         return ;
2388     size-- ;
2389     switch (aop->type) {
2390         case AOP_R0 :
2391         case AOP_R1 :
2392             while (size--)
2393                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2394             break;          
2395         case AOP_DPTR :
2396         case AOP_DPTR2:
2397             if (aop->type == AOP_DPTR2)
2398             {
2399                 genSetDPTR(1);
2400             } 
2401             while (size--)
2402             {
2403                 pic16_emitcode("lcall","__decdptr");
2404             }
2405                 
2406             if (aop->type == AOP_DPTR2)
2407             {
2408                 genSetDPTR(0);
2409             }                
2410             break;  
2411
2412     }   
2413
2414 }
2415 #endif
2416
2417 #if 0
2418 /*-----------------------------------------------------------------*/
2419 /* opIsGptr: returns non-zero if the passed operand is             */   
2420 /* a generic pointer type.                                         */
2421 /*-----------------------------------------------------------------*/ 
2422 static int opIsGptr(operand *op)
2423 {
2424     sym_link *type = operandType(op);
2425     
2426     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2427     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2428     {
2429         return 1;
2430     }
2431     return 0;        
2432 }
2433 #endif
2434
2435 /*-----------------------------------------------------------------*/
2436 /* pic16_getDataSize - get the operand data size                         */
2437 /*-----------------------------------------------------------------*/
2438 int pic16_getDataSize(operand *op)
2439 {
2440     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2441
2442
2443     return AOP_SIZE(op);
2444
2445     // tsd- in the pic port, the genptr size is 1, so this code here
2446     // fails. ( in the 8051 port, the size was 4).
2447 #if 0
2448     int size;
2449     size = AOP_SIZE(op);
2450     if (size == GPTRSIZE)
2451     {
2452         sym_link *type = operandType(op);
2453         if (IS_GENPTR(type))
2454         {
2455             /* generic pointer; arithmetic operations
2456              * should ignore the high byte (pointer type).
2457              */
2458             size--;
2459     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2460         }
2461     }
2462     return size;
2463 #endif
2464 }
2465
2466 /*-----------------------------------------------------------------*/
2467 /* pic16_outAcc - output Acc                                             */
2468 /*-----------------------------------------------------------------*/
2469 void pic16_outAcc(operand *result)
2470 {
2471   int size,offset;
2472   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2473   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2474
2475
2476   size = pic16_getDataSize(result);
2477   if(size){
2478     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2479     size--;
2480     offset = 1;
2481     /* unsigned or positive */
2482     while(size--)
2483       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2484   }
2485
2486 }
2487
2488 /*-----------------------------------------------------------------*/
2489 /* pic16_outBitC - output a bit C                                  */
2490 /*                 Move to result the value of Carry flag -- VR    */
2491 /*-----------------------------------------------------------------*/
2492 void pic16_outBitC(operand *result)
2493 {
2494   int i;
2495
2496     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2497
2498     /* if the result is bit */
2499     if (AOP_TYPE(result) == AOP_CRY) {
2500         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2501         pic16_aopPut(AOP(result),"c",0);
2502     } else {
2503
2504         i = AOP_SIZE(result);
2505         while(i--) {
2506                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2507         }
2508         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2509     }
2510 }
2511
2512 /*-----------------------------------------------------------------*/
2513 /* pic16_outBitOp - output a bit from Op                           */
2514 /*                 Move to result the value of set/clr op -- VR    */
2515 /*-----------------------------------------------------------------*/
2516 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2517 {
2518   int i;
2519
2520     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2521
2522     /* if the result is bit */
2523     if (AOP_TYPE(result) == AOP_CRY) {
2524         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2525         pic16_aopPut(AOP(result),"c",0);
2526     } else {
2527
2528         i = AOP_SIZE(result);
2529         while(i--) {
2530                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2531         }
2532         pic16_emitpcode(POC_RRCF, pcop);          
2533         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2534     }
2535 }
2536
2537 /*-----------------------------------------------------------------*/
2538 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2539 /*-----------------------------------------------------------------*/
2540 void pic16_toBoolean(operand *oper)
2541 {
2542     int size = AOP_SIZE(oper) - 1;
2543     int offset = 1;
2544
2545     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2546
2547     if ( AOP_TYPE(oper) != AOP_ACC) {
2548       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2549     }
2550     while (size--) {
2551       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2552     }
2553 }
2554
2555
2556 #if !defined(GEN_Not)
2557 /*-----------------------------------------------------------------*/
2558 /* genNot - generate code for ! operation                          */
2559 /*-----------------------------------------------------------------*/
2560 static void pic16_genNot (iCode *ic)
2561 {
2562   symbol *tlbl;
2563   int size;
2564
2565   FENTRY;
2566   /* assign asmOps to operand & result */
2567   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2568   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2569
2570   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2571   /* if in bit space then a special case */
2572   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2573     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2574       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2575       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2576     } else {
2577       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2578       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2579       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2580     }
2581     goto release;
2582   }
2583
2584   size = AOP_SIZE(IC_LEFT(ic));
2585   if(size == 1) {
2586     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2587     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2588     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2589     goto release;
2590   }
2591   pic16_toBoolean(IC_LEFT(ic));
2592
2593   tlbl = newiTempLabel(NULL);
2594   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2595   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2596   pic16_outBitC(IC_RESULT(ic));
2597
2598  release:    
2599   /* release the aops */
2600   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2601   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2602 }
2603 #endif
2604
2605
2606 #if !defined(GEN_Cpl)
2607 /*-----------------------------------------------------------------*/
2608 /* genCpl - generate code for complement                           */
2609 /*-----------------------------------------------------------------*/
2610 static void pic16_genCpl (iCode *ic)
2611 {
2612   int offset = 0;
2613   int size ;
2614
2615     FENTRY;
2616     /* assign asmOps to operand & result */
2617     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2618     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2619
2620     /* if both are in bit space then 
2621     a special case */
2622     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2623         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2624
2625         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2626         pic16_emitcode("cpl","c"); 
2627         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2628         goto release; 
2629     } 
2630
2631     size = AOP_SIZE(IC_RESULT(ic));
2632     while (size--) {
2633 /*
2634         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2635         MOVA(l);       
2636         pic16_emitcode("cpl","a");
2637         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2638 */
2639         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2640               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2641         } else {
2642                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2643                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2644         }
2645         offset++;
2646
2647     }
2648
2649
2650 release:
2651     /* release the aops */
2652     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2653     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2654 }
2655 #endif
2656
2657 /*-----------------------------------------------------------------*/
2658 /* genUminusFloat - unary minus for floating points                */
2659 /*-----------------------------------------------------------------*/
2660 static void genUminusFloat(operand *op,operand *result)
2661 {
2662   int size ,offset =0 ;
2663   
2664     FENTRY;
2665     /* for this we just need to flip the 
2666     first it then copy the rest in place */
2667     size = AOP_SIZE(op);
2668
2669     while(size--) {
2670       mov2f(AOP(result), AOP(op), offset);
2671       offset++;
2672     }
2673     
2674     /* toggle the MSB's highest bit */
2675     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2676 }
2677
2678 /*-----------------------------------------------------------------*/
2679 /* genUminus - unary minus code generation                         */
2680 /*-----------------------------------------------------------------*/
2681 static void genUminus (iCode *ic)
2682 {
2683   int size, i;
2684   sym_link *optype, *rtype;
2685   symbol *label;
2686   int needLabel=0;
2687
2688     FENTRY;     
2689     
2690     /* assign asmops */
2691     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2692     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2693
2694     /* if both in bit space then special case */
2695     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2696       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2697         
2698         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2699         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2700         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2701         goto release; 
2702     } 
2703
2704     optype = operandType(IC_LEFT(ic));
2705     rtype = operandType(IC_RESULT(ic));
2706
2707     /* if float then do float stuff */
2708     if (IS_FLOAT(optype)) {
2709       genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2710       goto release;
2711     }
2712
2713     /* otherwise subtract from zero by taking the 2's complement */
2714     size = AOP_SIZE(IC_LEFT(ic));
2715     label = newiTempLabel ( NULL );
2716     
2717     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2718       for (i=size-1; i > 0; i--) {
2719         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2720       } // for
2721       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2722       for (i=1; i < size; i++) {
2723         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2724         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2725       } // for
2726     } else {
2727       for (i=size-1; i >= 0; i--) {
2728         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2729         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2730       } // for
2731       if (size > 1) {
2732         for (i=0; i < size-2; i++) {
2733           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2734           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2735         } // for
2736         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2737       } // if
2738       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2739     }
2740     if (needLabel)
2741       pic16_emitpLabel (label->key);
2742
2743 release:
2744     /* release the aops */
2745     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2746     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2747 }
2748
2749 #if 0
2750 /*-----------------------------------------------------------------*/
2751 /* saveRegisters - will look for a call and save the registers     */
2752 /*-----------------------------------------------------------------*/
2753 static void saveRegisters(iCode *lic) 
2754 {
2755     int i;
2756     iCode *ic;
2757     bitVect *rsave;
2758     sym_link *dtype;
2759
2760     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2761     /* look for call */
2762     for (ic = lic ; ic ; ic = ic->next) 
2763         if (ic->op == CALL || ic->op == PCALL)
2764             break;
2765
2766     if (!ic) {
2767         fprintf(stderr,"found parameter push with no function call\n");
2768         return ;
2769     }
2770
2771     /* if the registers have been saved already then
2772     do nothing */
2773     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2774         return ;
2775
2776     /* find the registers in use at this time 
2777     and push them away to safety */
2778     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2779                           ic->rUsed);
2780
2781     ic->regsSaved = 1;
2782     if (options.useXstack) {
2783         if (bitVectBitValue(rsave,R0_IDX))
2784             pic16_emitcode("mov","b,r0");
2785         pic16_emitcode("mov","r0,%s",spname);
2786         for (i = 0 ; i < pic16_nRegs ; i++) {
2787             if (bitVectBitValue(rsave,i)) {
2788                 if (i == R0_IDX)
2789                     pic16_emitcode("mov","a,b");
2790                 else
2791                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2792                 pic16_emitcode("movx","@r0,a");
2793                 pic16_emitcode("inc","r0");
2794             }
2795         }
2796         pic16_emitcode("mov","%s,r0",spname);
2797         if (bitVectBitValue(rsave,R0_IDX))
2798             pic16_emitcode("mov","r0,b");           
2799     }// else
2800     //for (i = 0 ; i < pic16_nRegs ; i++) {
2801     //    if (bitVectBitValue(rsave,i))
2802     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2803     //}
2804
2805     dtype = operandType(IC_LEFT(ic));
2806     if (currFunc && dtype && 
2807         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2808         IFFUNC_ISISR(currFunc->type) &&
2809         !ic->bankSaved) 
2810
2811         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2812
2813 }
2814 /*-----------------------------------------------------------------*/
2815 /* unsaveRegisters - pop the pushed registers                      */
2816 /*-----------------------------------------------------------------*/
2817 static void unsaveRegisters (iCode *ic)
2818 {
2819     int i;
2820     bitVect *rsave;
2821
2822     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2823     /* find the registers in use at this time 
2824     and push them away to safety */
2825     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2826                           ic->rUsed);
2827     
2828     if (options.useXstack) {
2829         pic16_emitcode("mov","r0,%s",spname);   
2830         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2831             if (bitVectBitValue(rsave,i)) {
2832                 pic16_emitcode("dec","r0");
2833                 pic16_emitcode("movx","a,@r0");
2834                 if (i == R0_IDX)
2835                     pic16_emitcode("mov","b,a");
2836                 else
2837                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2838             }       
2839
2840         }
2841         pic16_emitcode("mov","%s,r0",spname);
2842         if (bitVectBitValue(rsave,R0_IDX))
2843             pic16_emitcode("mov","r0,b");
2844     } //else
2845     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2846     //    if (bitVectBitValue(rsave,i))
2847     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2848     //}
2849
2850 }  
2851 #endif
2852
2853 #if 0  // patch 14
2854 /*-----------------------------------------------------------------*/
2855 /* pushSide -                                                      */
2856 /*-----------------------------------------------------------------*/
2857 static void pushSide(operand * oper, int size)
2858 {
2859         int offset = 0;
2860     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2861         while (size--) {
2862                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2863                 if (AOP_TYPE(oper) != AOP_REG &&
2864                     AOP_TYPE(oper) != AOP_DIR &&
2865                     strcmp(l,"a") ) {
2866                         pic16_emitcode("mov","a,%s",l);
2867                         pic16_emitcode("push","acc");
2868                 } else
2869                         pic16_emitcode("push","%s",l);
2870         }
2871 }
2872 #endif // patch 14
2873
2874 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2875 {
2876   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2877     pic16_emitpcode(POC_MOVFW, src);
2878     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2879   } else {
2880     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2881         src, pic16_popGet(AOP(op), offset)));
2882   }
2883 }
2884
2885
2886 /*-----------------------------------------------------------------*/
2887 /* assignResultValue - assign results to oper, rescall==1 is       */
2888 /*                     called from genCall() or genPcall()         */
2889 /*-----------------------------------------------------------------*/
2890 static void assignResultValue(operand * oper, int rescall)
2891 {
2892   int size = AOP_SIZE(oper);
2893   int offset=0;
2894   
2895     FENTRY2;
2896 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2897     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2898
2899     if(rescall) {
2900       /* assign result from a call/pcall function() */
2901                 
2902       /* function results are stored in a special order,
2903        * see top of file with Function return policy, or manual */
2904
2905       if(size <= 4) {
2906         /* 8-bits, result in WREG */
2907         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2908                         
2909         if(size>1) {
2910           /* 16-bits, result in PRODL:WREG */
2911           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2912         }
2913                         
2914         if(size>2) {
2915           /* 24-bits, result in PRODH:PRODL:WREG */
2916           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2917         }
2918                         
2919         if(size>3) {
2920           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2921           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2922         }
2923       
2924       } else {
2925         /* >32-bits, result on stack, and FSR0 points to beginning.
2926          * Fix stack when done */
2927         /* FIXME FIXME */
2928 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2929         while (size--) {
2930 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2931 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2932                 
2933           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2934           GpsuedoStkPtr++;
2935         }
2936                         
2937         /* fix stack */
2938         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2939         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
2940         if(STACK_MODEL_LARGE) {
2941           emitSKPNC;
2942           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
2943         }
2944       }                 
2945     } else {
2946       int areg = 0;             /* matching argument register */
2947       
2948 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2949       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2950
2951
2952       /* its called from genReceive (probably) -- VR */
2953       /* I hope this code will not be called from somewhere else in the future! 
2954        * We manually set the pseudo stack pointer in genReceive. - dw
2955        */
2956       if(!GpsuedoStkPtr && _G.useWreg) {
2957 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2958
2959         /* The last byte in the assignment is in W */
2960         if(areg <= GpsuedoStkPtr) {
2961           size--;
2962           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2963           offset++;
2964 //          debugf("receive from WREG\n", 0);
2965         }
2966         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
2967       }
2968 //      GpsuedoStkPtr++;
2969       _G.stack_lat = AOP_SIZE(oper)-1;
2970
2971       while (size) {
2972         size--;
2973         GpsuedoStkPtr++;
2974         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
2975 //        debugf("receive from STACK\n", 0);
2976         offset++;
2977       }
2978     }
2979 }
2980
2981
2982 /*-----------------------------------------------------------------*/
2983 /* genIpush - generate code for pushing this gets a little complex */
2984 /*-----------------------------------------------------------------*/
2985 static void genIpush (iCode *ic)
2986 {
2987 //  int size, offset=0;
2988
2989   FENTRY;
2990   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2991
2992   if(ic->parmPush) {
2993     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2994
2995     /* send to stack as normal */
2996     addSet(&_G.sendSet,ic);
2997 //    addSetHead(&_G.sendSet,ic);
2998     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2999   }
3000
3001         
3002 #if 0
3003     int size, offset = 0 ;
3004     char *l;
3005
3006
3007     /* if this is not a parm push : ie. it is spill push 
3008     and spill push is always done on the local stack */
3009     if (!ic->parmPush) {
3010
3011         /* and the item is spilt then do nothing */
3012         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3013             return ;
3014
3015         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3016         size = AOP_SIZE(IC_LEFT(ic));
3017         /* push it on the stack */
3018         while(size--) {
3019             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3020             if (*l == '#') {
3021                 MOVA(l);
3022                 l = "acc";
3023             }
3024             pic16_emitcode("push","%s",l);
3025         }
3026         return ;        
3027     }
3028
3029     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3030 #endif
3031 }
3032
3033 /*-----------------------------------------------------------------*/
3034 /* genIpop - recover the registers: can happen only for spilling   */
3035 /*-----------------------------------------------------------------*/
3036 static void genIpop (iCode *ic)
3037 {
3038   FENTRY;
3039   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3040 #if 0
3041     int size,offset ;
3042
3043
3044     /* if the temp was not pushed then */
3045     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3046         return ;
3047
3048     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3049     size = AOP_SIZE(IC_LEFT(ic));
3050     offset = (size-1);
3051     while (size--) 
3052         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3053                                    FALSE,TRUE));
3054
3055     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3056 #endif
3057 }
3058
3059 #if 0
3060 /*-----------------------------------------------------------------*/
3061 /* unsaverbank - restores the resgister bank from stack            */
3062 /*-----------------------------------------------------------------*/
3063 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3064 {
3065   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3066 #if 0
3067     int i;
3068     asmop *aop ;
3069     regs *r = NULL;
3070
3071     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3072     if (popPsw) {
3073         if (options.useXstack) {
3074             aop = newAsmop(0);
3075             r = getFreePtr(ic,&aop,FALSE);
3076             
3077             
3078             pic16_emitcode("mov","%s,_spx",r->name);
3079             pic16_emitcode("movx","a,@%s",r->name);
3080             pic16_emitcode("mov","psw,a");
3081             pic16_emitcode("dec","%s",r->name);
3082             
3083         }else
3084             pic16_emitcode ("pop","psw");
3085     }
3086
3087     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3088         if (options.useXstack) {       
3089             pic16_emitcode("movx","a,@%s",r->name);
3090             //pic16_emitcode("mov","(%s+%d),a",
3091             //       regspic16[i].base,8*bank+regspic16[i].offset);
3092             pic16_emitcode("dec","%s",r->name);
3093
3094         } else 
3095           pic16_emitcode("pop",""); //"(%s+%d)",
3096         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3097     }
3098
3099     if (options.useXstack) {
3100
3101         pic16_emitcode("mov","_spx,%s",r->name);
3102         pic16_freeAsmop(NULL,aop,ic,TRUE);
3103
3104     }
3105 #endif 
3106 }
3107
3108 /*-----------------------------------------------------------------*/
3109 /* saverbank - saves an entire register bank on the stack          */
3110 /*-----------------------------------------------------------------*/
3111 static void saverbank (int bank, iCode *ic, bool pushPsw)
3112 {
3113   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3114 #if 0
3115     int i;
3116     asmop *aop ;
3117     regs *r = NULL;
3118
3119     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3120     if (options.useXstack) {
3121
3122         aop = newAsmop(0);
3123         r = getFreePtr(ic,&aop,FALSE);  
3124         pic16_emitcode("mov","%s,_spx",r->name);
3125
3126     }
3127
3128     for (i = 0 ; i < pic16_nRegs ;i++) {
3129         if (options.useXstack) {
3130             pic16_emitcode("inc","%s",r->name);
3131             //pic16_emitcode("mov","a,(%s+%d)",
3132             //         regspic16[i].base,8*bank+regspic16[i].offset);
3133             pic16_emitcode("movx","@%s,a",r->name);           
3134         } else 
3135           pic16_emitcode("push","");// "(%s+%d)",
3136                      //regspic16[i].base,8*bank+regspic16[i].offset);
3137     }
3138     
3139     if (pushPsw) {
3140         if (options.useXstack) {
3141             pic16_emitcode("mov","a,psw");
3142             pic16_emitcode("movx","@%s,a",r->name);     
3143             pic16_emitcode("inc","%s",r->name);
3144             pic16_emitcode("mov","_spx,%s",r->name);       
3145             pic16_freeAsmop (NULL,aop,ic,TRUE);
3146             
3147         } else
3148             pic16_emitcode("push","psw");
3149         
3150         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3151     }
3152     ic->bankSaved = 1;
3153 #endif
3154 }
3155 #endif  /* 0 */
3156
3157
3158 static int wparamCmp(void *p1, void *p2)
3159 {
3160   return (!strcmp((char *)p1, (char *)p2));
3161 }
3162
3163 int inWparamList(char *s)
3164 {
3165   return isinSetWith(wparamList, s, wparamCmp);
3166
3167
3168
3169 /*-----------------------------------------------------------------*/
3170 /* genCall - generates a call statement                            */
3171 /*-----------------------------------------------------------------*/
3172 static void genCall (iCode *ic)
3173 {
3174   sym_link *ftype;   
3175   int stackParms=0;
3176   int use_wreg=0;
3177   int inwparam=0;
3178   char *fname;
3179   
3180     FENTRY;
3181
3182     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3183     /* if caller saves & we have not saved then */
3184 //    if (!ic->regsSaved)
3185 //      saveRegisters(ic);
3186
3187         /* initialise stackParms for IPUSH pushes */
3188 //      stackParms = psuedoStkPtr;
3189 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3190     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3191     inwparam = inWparamList(OP_SYMBOL(IC_LEFT(ic))->name);
3192
3193 #if 0
3194     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3195 #endif
3196
3197     /* if send set is not empty the assign */
3198     if (_G.sendSet) {
3199       iCode *sic;
3200       int psuedoStkPtr=-1; 
3201       int firstTimeThruLoop = 1;
3202
3203
3204         /* reverse sendSet if function is not reentrant */
3205         if(!IFFUNC_ISREENT(ftype))
3206           _G.sendSet = reverseSet(_G.sendSet);
3207
3208         /* First figure how many parameters are getting passed */
3209         stackParms = 0;
3210         use_wreg = 0;
3211         
3212         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3213           int size;
3214 //          int offset = 0;
3215
3216             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3217             size = AOP_SIZE(IC_LEFT(sic));
3218
3219             stackParms += size;
3220
3221             /* pass the last byte through WREG */
3222             if(inwparam) {
3223
3224               while (size--) {
3225                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3226                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3227                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3228
3229                 if(!firstTimeThruLoop) {
3230                   /* If this is not the first time we've been through the loop
3231                    * then we need to save the parameter in a temporary
3232                    * register. The last byte of the last parameter is
3233                    * passed in W. */
3234
3235                   pushw();
3236 //                  --psuedoStkPtr;             // sanity check
3237                   use_wreg = 1;
3238                 }
3239                 
3240                 firstTimeThruLoop=0;
3241
3242                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3243
3244 //                offset++;
3245               }
3246             } else {
3247               /* all arguments are passed via stack */
3248               use_wreg = 0;
3249
3250               while (size--) {
3251                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3252                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3253                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3254
3255 //                pushaop(AOP(IC_LEFT(sic)), size);
3256                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3257                 pushw();
3258               }
3259             }
3260
3261             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3262           }
3263
3264           if(inwparam) {
3265             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3266               pushw();  /* save last parameter to stack if functions has varargs */
3267               use_wreg = 0;
3268             } else
3269               use_wreg = 1;
3270           } else use_wreg = 0;
3271
3272           _G.stackRegSet = _G.sendSet;
3273           _G.sendSet = NULL;
3274     }
3275
3276     /* make the call */
3277     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3278
3279     GpsuedoStkPtr=0;
3280     
3281     /* if we need to assign a result value */
3282     if ((IS_ITEMP(IC_RESULT(ic))
3283           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3284               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3285         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3286
3287       _G.accInUse++;
3288       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3289       _G.accInUse--;
3290
3291       assignResultValue(IC_RESULT(ic), 1);
3292
3293       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3294                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3295                 
3296       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3297     }
3298
3299     if(!stackParms && ic->parmBytes) {
3300       stackParms = ic->parmBytes;
3301     }
3302       
3303     stackParms -= use_wreg;
3304     
3305     if(stackParms>0) {
3306       if(stackParms == 1) {
3307         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3308       } else {
3309         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3310         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3311       }
3312       if(STACK_MODEL_LARGE) {
3313         emitSKPNC;
3314         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3315       }
3316     }
3317
3318 #if 0
3319     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3320 #endif
3321
3322     /* adjust the stack for parameters if required */
3323 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3324
3325 #if 0
3326       /* if register bank was saved then pop them */
3327       if (ic->bankSaved)
3328         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3329
3330       /* if we hade saved some registers then unsave them */
3331       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3332         unsaveRegisters (ic);
3333 #endif
3334 }
3335
3336
3337
3338 /*-----------------------------------------------------------------*/
3339 /* genPcall - generates a call by pointer statement                */
3340 /*            new version, created from genCall - HJD              */
3341 /*-----------------------------------------------------------------*/
3342 static void genPcall (iCode *ic)
3343 {
3344   sym_link *ftype, *fntype;
3345   int stackParms=0;
3346   symbol *retlbl = newiTempLabel(NULL);
3347   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3348   
3349     FENTRY;
3350
3351     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3352     fntype = operandType( IC_LEFT(ic) )->next;
3353
3354     /* if send set is not empty the assign */
3355     if (_G.sendSet) {
3356       iCode *sic;
3357       int psuedoStkPtr=-1; 
3358
3359       /* reverse sendSet if function is not reentrant */
3360       if(!IFFUNC_ISREENT(fntype))
3361         _G.sendSet = reverseSet(_G.sendSet);
3362
3363       stackParms = 0;
3364       
3365       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3366         int size;
3367
3368           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3369           size = AOP_SIZE(IC_LEFT(sic));
3370           stackParms += size;
3371
3372           /* all parameters are passed via stack, since WREG is clobbered
3373            * by the calling sequence */
3374           while (size--) {
3375             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3376             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3377             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3378
3379             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3380             pushw();
3381           }
3382
3383           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3384       }
3385
3386       _G.stackRegSet = _G.sendSet;
3387       _G.sendSet = NULL;
3388     }
3389
3390     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3391
3392     // push return address
3393     // push $ on return stack, then replace with retlbl
3394
3395     pic16_emitpcodeNULLop(POC_PUSH);
3396
3397     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3398     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3399     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3400     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3401     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3402     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3403
3404     /* make the call by writing the pointer into pc */
3405     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3406     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3407
3408     // note: MOVFF to PCL not allowed
3409     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3410     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3411
3412
3413     /* return address is here: (X) */
3414     pic16_emitpLabelFORCE(retlbl->key);
3415
3416     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3417
3418     GpsuedoStkPtr=0;
3419     /* if we need assign a result value */
3420     if ((IS_ITEMP(IC_RESULT(ic))
3421           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3422               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3423         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3424
3425       _G.accInUse++;
3426       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3427       _G.accInUse--;
3428
3429       assignResultValue(IC_RESULT(ic), 1);
3430
3431       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3432               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3433                 
3434       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3435     }
3436
3437 //    stackParms -= use_wreg;
3438     
3439     if(stackParms>0) {
3440       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3441       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3442       if(STACK_MODEL_LARGE) {
3443         emitSKPNC;
3444         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3445       }
3446     }
3447 }
3448
3449 /*-----------------------------------------------------------------*/
3450 /* resultRemat - result  is rematerializable                       */
3451 /*-----------------------------------------------------------------*/
3452 static int resultRemat (iCode *ic)
3453 {
3454   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3455   if (SKIP_IC(ic) || ic->op == IFX)
3456     return 0;
3457
3458   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3459     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3460     if (sym->remat && !POINTER_SET(ic)) 
3461       return 1;
3462   }
3463
3464   return 0;
3465 }
3466
3467 #if defined(__BORLANDC__) || defined(_MSC_VER)
3468 #define STRCASECMP stricmp
3469 #else
3470 #define STRCASECMP strcasecmp
3471 #endif
3472
3473 #if 0
3474 /*-----------------------------------------------------------------*/
3475 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3476 /*-----------------------------------------------------------------*/
3477 static bool inExcludeList(char *s)
3478 {
3479   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3480     int i =0;
3481     
3482     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3483     if (options.excludeRegs[i] &&
3484     STRCASECMP(options.excludeRegs[i],"none") == 0)
3485         return FALSE ;
3486
3487     for ( i = 0 ; options.excludeRegs[i]; i++) {
3488         if (options.excludeRegs[i] &&
3489         STRCASECMP(s,options.excludeRegs[i]) == 0)
3490             return TRUE;
3491     }
3492     return FALSE ;
3493 }
3494 #endif
3495
3496 /*-----------------------------------------------------------------*/
3497 /* genFunction - generated code for function entry                 */
3498 /*-----------------------------------------------------------------*/
3499 static void genFunction (iCode *ic)
3500 {
3501   symbol *sym;
3502   sym_link *ftype;
3503   
3504     FENTRY;
3505     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3506
3507     pic16_labelOffset += (max_key+4);
3508     max_key=0;
3509     GpsuedoStkPtr=0;
3510     _G.nRegsSaved = 0;
3511         
3512     ftype = operandType(IC_LEFT(ic));
3513     sym = OP_SYMBOL(IC_LEFT(ic));
3514
3515     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3516       /* create an absolute section at the interrupt vector:
3517        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3518       symbol *asym;
3519       char asymname[128];
3520       pBlock *apb;
3521
3522         {
3523           int i, found=-1;
3524
3525             sym = OP_SYMBOL( IC_LEFT(ic));
3526             for(i=0;i<=2;i++) {
3527               if(interrupts[i]->name
3528                     && !STRCASECMP(interrupts[i]->name, sym->name)) {
3529                   found = i;
3530                   break;
3531               }
3532             }
3533                         
3534             if(found == -1) {
3535               fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3536                             __FILE__, __LINE__, sym->name);
3537               assert( 0 );
3538             }
3539             _G.interruptvector = found;
3540         }
3541
3542         sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3543         asym = newSymbol(asymname, 0);
3544
3545         apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3546         pic16_addpBlock( apb );
3547
3548         pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3549         pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3550         pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3551                 
3552         /* mark the end of this tiny function */
3553         pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3554
3555         {
3556           absSym *abSym;
3557
3558             abSym = Safe_calloc(1, sizeof(absSym));
3559             strcpy(abSym->name, asymname);
3560
3561             switch( _G.interruptvector ) {
3562               case 0: abSym->address = 0x000000; break;
3563               case 1: abSym->address = 0x000008; break;
3564               case 2: abSym->address = 0x000018; break;
3565             }
3566
3567             /* relocate interrupt vectors if needed */
3568             abSym->address += pic16_options.ivt_loc;
3569
3570             addSet(&absSymSet, abSym);
3571         }
3572     }
3573
3574     /* create the function header */
3575     pic16_emitcode(";","-----------------------------------------");
3576     pic16_emitcode(";"," function %s",sym->name);
3577     pic16_emitcode(";","-----------------------------------------");
3578
3579     pic16_emitcode("","%s:",sym->rname);
3580     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3581
3582
3583     {
3584       absSym *ab;
3585
3586         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3587           if(!strcmp(ab->name, sym->rname)) {
3588             pic16_pBlockConvert2Absolute(pb);
3589             break;
3590           }
3591         }
3592     }
3593
3594
3595     if(IFFUNC_ISNAKED(ftype)) {
3596       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3597       return;
3598     }
3599         
3600     /* if critical function then turn interrupts off */
3601     if (IFFUNC_ISCRITICAL(ftype)) {
3602       //pic16_emitcode("clr","ea");
3603     }
3604
3605     _G.fregsUsed = sym->regsUsed;
3606
3607     /* if this is an interrupt service routine then
3608      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3609     if (IFFUNC_ISISR(sym->type)) {
3610         _G.usefastretfie = 1;   /* use shadow registers by default */
3611         
3612         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3613         if(!(_G.interruptvector == 1)) {
3614           /* do not save WREG,STATUS,BSR for high priority interrupts
3615            * because they are stored in the hardware shadow registers already */
3616           _G.usefastretfie = 0;
3617           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3618           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3619           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3620         }
3621
3622         /* these should really be optimized somehow, because not all
3623          * interrupt handlers modify them */
3624         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3625         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3626         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3627         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3628         
3629 //        pic16_pBlockConvert2ISR(pb);
3630                 
3631     }
3632
3633     /* emit code to setup stack frame if user enabled,
3634      * and function is not main() */
3635          
3636     //fprintf(stderr, "function name: %s\n", sym->name);
3637     if(strcmp(sym->name, "main")) {
3638       if(1  /*!options.ommitFramePtr || sym->regsUsed*/) {
3639         /* setup the stack frame */
3640         if(STACK_MODEL_LARGE)
3641           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3642         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3643
3644         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3645         if(STACK_MODEL_LARGE)
3646           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3647       }
3648     }
3649
3650     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3651           && sym->stack) {
3652
3653       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3654
3655       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3656       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3657       emitSKPC;
3658       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3659     }
3660           
3661     if(inWparamList(sym->name)) {
3662       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3663         _G.useWreg = 0;
3664       else
3665         _G.useWreg = 1;
3666     } else
3667       _G.useWreg = 0;
3668
3669     /* if callee-save to be used for this function
3670      * then save the registers being used in this function */
3671 //    if (IFFUNC_CALLEESAVES(sym->type))
3672     {
3673       int i;
3674
3675         /* if any registers used */
3676         if (sym->regsUsed) {
3677           /* save the registers used */
3678           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3679           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3680           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3681             if (bitVectBitValue(sym->regsUsed,i)) {
3682               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3683               _G.nRegsSaved++;
3684
3685               if(!pic16_regWithIdx(i)->wasUsed) {
3686                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3687                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3688                 pic16_regWithIdx(i)->wasUsed = 1;
3689               }
3690             }
3691           }
3692           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3693         }
3694     }
3695         
3696     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3697 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3698 }
3699
3700 /*-----------------------------------------------------------------*/
3701 /* genEndFunction - generates epilogue for functions               */
3702 /*-----------------------------------------------------------------*/
3703 static void genEndFunction (iCode *ic)
3704 {
3705   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3706
3707     FENTRY;
3708
3709     if(IFFUNC_ISNAKED(sym->type)) {
3710       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3711       return;
3712     }
3713
3714     _G.stack_lat = 0;
3715
3716     /* add code for ISCRITICAL */
3717     if(IFFUNC_ISCRITICAL(sym->type)) {
3718       /* if critical function, turn on interrupts */
3719       
3720       /* TODO: add code here -- VR */
3721     }
3722     
3723 //    sym->regsUsed = _G.fregsUsed;
3724     
3725     /* now we need to restore the registers */
3726     /* if any registers used */
3727     if (sym->regsUsed) {
3728       int i;
3729
3730         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3731         /* restore registers used */
3732         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3733         for ( i = sym->regsUsed->size; i >= 0; i--) {
3734           if (bitVectBitValue(sym->regsUsed,i)) {
3735             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3736             _G.nRegsSaved--;
3737           }
3738         }
3739         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3740
3741     }
3742
3743     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3744           && sym->stack) {
3745       if (sym->stack == 1) {
3746         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3747         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3748       } else {
3749         // we have to add more than one...
3750         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3751         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3752         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3753         emitSKPNC;
3754         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3755         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3756         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3757       }
3758     }
3759
3760     if(strcmp(sym->name, "main")) {
3761       if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3762         /* restore stack frame */
3763         if(STACK_MODEL_LARGE)
3764           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3765         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3766       }
3767     }
3768
3769     _G.useWreg = 0;
3770
3771     if (IFFUNC_ISISR(sym->type)) {
3772       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3773       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3774       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3775       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3776
3777       if(!(_G.interruptvector == 1)) {
3778         /* do not restore interrupt vector for WREG,STATUS,BSR
3779          * for high priority interrupt, see genFunction */
3780         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3781         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3782         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3783       }
3784       _G.interruptvector = 0;           /* sanity check */
3785
3786
3787       /* if debug then send end of function */
3788 /*      if (options.debug && currFunc)  */
3789       if (currFunc) {
3790         debugFile->writeEndFunction (currFunc, ic, 1);
3791       }
3792         
3793       if(_G.usefastretfie)
3794         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3795       else
3796         pic16_emitpcodeNULLop(POC_RETFIE);
3797
3798       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3799       
3800       _G.usefastretfie = 0;
3801       return;
3802     }
3803
3804     if (IFFUNC_ISCRITICAL(sym->type)) {
3805       pic16_emitcode("setb","ea");
3806     }
3807
3808     /* if debug then send end of function */
3809     if (currFunc) {
3810       debugFile->writeEndFunction (currFunc, ic, 1);
3811     }
3812
3813     /* insert code to restore stack frame, if user enabled it
3814      * and function is not main() */
3815          
3816
3817     pic16_emitpcodeNULLop(POC_RETURN);
3818
3819     /* Mark the end of a function */
3820     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3821 }
3822
3823
3824 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3825 {
3826   if(is_LitOp(op)) {
3827     unsigned long lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3828       if(lit == 0) {
3829         pic16_emitpcode(POC_CLRF, dest);
3830       } else {
3831         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3832         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3833       }
3834   } else {
3835     if(dest->type == PO_WREG && (offset == 0)) {
3836       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3837       return;
3838     }
3839     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3840   }
3841 }
3842
3843 /*-----------------------------------------------------------------*/
3844 /* genRet - generate code for return statement                     */
3845 /*-----------------------------------------------------------------*/
3846 static void genRet (iCode *ic)
3847 {
3848   int size;
3849   operand *left;
3850
3851     FENTRY;
3852         /* if we have no return value then
3853          * just generate the "ret" */
3854         
3855         if (!IC_LEFT(ic)) 
3856                 goto jumpret;       
3857     
3858         /* we have something to return then
3859          * move the return value into place */
3860         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3861         size = AOP_SIZE(IC_LEFT(ic));
3862
3863         if(size <= 4) {
3864                 if(size>3) {
3865                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3866 //                      pic16_emitpcode(POC_MOVFF,
3867 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3868                 }
3869                 if(size>2) {
3870                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3871 //                      pic16_emitpcode(POC_MOVFF,
3872 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3873                 }
3874                 if(size>1) {
3875                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3876 //                      pic16_emitpcode(POC_MOVFF,
3877 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3878                 }
3879
3880 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3881
3882                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3883 //              pic16_emitpcode(POC_MOVFF,
3884 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3885
3886         } else {
3887                 /* >32-bits, setup stack and FSR0 */
3888                 while (size--) {
3889 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3890 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3891
3892                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3893
3894 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3895                         GpsuedoStkPtr++;
3896                 }
3897                         
3898                 /* setup FSR0 */
3899                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3900                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3901
3902                 if(STACK_MODEL_LARGE) {
3903                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3904                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3905                 } else {
3906                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3907                 }
3908         }
3909                                 
3910 #if 0
3911         /* old code, left here for reference -- VR */    
3912         while (size--) {
3913           char *l ;
3914
3915                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3916                         /* #NOCHANGE */
3917                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3918                         pic16_emitpcomment("push %s",l);
3919                         pushed++;
3920                 } else {
3921                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3922                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3923                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3924                         
3925                         if (strcmp(fReturn[offset],l)) {
3926                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3927                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3928                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3929                                 } else {
3930                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3931                                 }
3932                                 
3933                                 if(size) {
3934                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3935                                 }
3936                                 offset++;
3937                         }
3938                 }
3939         }    
3940
3941         if (pushed) {
3942                 while(pushed) {
3943                         pushed--;
3944                         if (strcmp(fReturn[pushed],"a"))
3945                                 pic16_emitcode("pop",fReturn[pushed]);
3946                         else
3947                                 pic16_emitcode("pop","acc");
3948                 }
3949         }
3950 #endif
3951
3952
3953         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3954     
3955 jumpret:
3956         /* generate a jump to the return label
3957          * if the next is not the return statement */
3958         if (!(ic->next && ic->next->op == LABEL
3959                 && IC_LABEL(ic->next) == returnLabel)) {
3960         
3961                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3962                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3963         }
3964 }
3965
3966 /*-----------------------------------------------------------------*/
3967 /* genLabel - generates a label                                    */
3968 /*-----------------------------------------------------------------*/
3969 static void genLabel (iCode *ic)
3970 {
3971   FENTRY;
3972
3973   /* special case never generate */
3974   if (IC_LABEL(ic) == entryLabel)
3975     return ;
3976
3977   pic16_emitpLabel(IC_LABEL(ic)->key);
3978 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3979 }
3980
3981 /*-----------------------------------------------------------------*/
3982 /* genGoto - generates a goto                                      */
3983 /*-----------------------------------------------------------------*/
3984 //tsd
3985 static void genGoto (iCode *ic)
3986 {
3987   FENTRY;
3988   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3989 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3990 }
3991
3992
3993 /*-----------------------------------------------------------------*/
3994 /* genMultbits :- multiplication of bits                           */
3995 /*-----------------------------------------------------------------*/
3996 static void genMultbits (operand *left, 
3997                          operand *right, 
3998                          operand *result)
3999 {
4000   FENTRY;
4001
4002   if(!pic16_sameRegs(AOP(result),AOP(right)))
4003     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4004
4005   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4006   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4007   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4008
4009 }
4010
4011
4012 /*-----------------------------------------------------------------*/
4013 /* genMultOneByte : 8 bit multiplication & division                */
4014 /*-----------------------------------------------------------------*/
4015 static void genMultOneByte (operand *left,
4016                             operand *right,
4017                             operand *result)
4018 {
4019
4020   FENTRY;
4021   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4022   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4023
4024   /* (if two literals, the value is computed before) */
4025   /* if one literal, literal on the right */
4026   if (AOP_TYPE(left) == AOP_LIT){
4027     operand *t = right;
4028     right = left;
4029     left = t;
4030   }
4031
4032         /* size is already checked in genMult == 1 */
4033 //      size = AOP_SIZE(result);
4034
4035         if (AOP_TYPE(right) == AOP_LIT){
4036                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4037                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4038                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4039                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4040         } else {
4041                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4042                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4043                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4044                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4045         }
4046         
4047         pic16_genMult8X8_8 (left, right,result);
4048 }
4049
4050 /*-----------------------------------------------------------------*/
4051 /* genMultOneWord : 16 bit multiplication                          */
4052 /*-----------------------------------------------------------------*/
4053 static void genMultOneWord (operand *left,
4054                             operand *right,
4055                             operand *result)
4056 {
4057   FENTRY;
4058   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4059   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4060
4061   /* (if two literals, the value is computed before)
4062    * if one literal, literal on the right */
4063   if (AOP_TYPE(left) == AOP_LIT){
4064     operand *t = right;
4065     right = left;
4066     left = t;
4067   }
4068
4069   /* size is checked already == 2 */
4070 //  size = AOP_SIZE(result);
4071
4072   if (AOP_TYPE(right) == AOP_LIT) {
4073     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4074       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4075       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4076       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4077   } else {
4078     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4079       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4080       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4081       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4082   }
4083         
4084   pic16_genMult16X16_16(left, right,result);
4085 }
4086
4087 /*-----------------------------------------------------------------*/
4088 /* genMultOneLong : 32 bit multiplication                          */
4089 /*-----------------------------------------------------------------*/
4090 static void genMultOneLong (operand *left,
4091                             operand *right,
4092                             operand *result)
4093 {
4094   FENTRY;
4095   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4096   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4097
4098   /* (if two literals, the value is computed before)
4099    * if one literal, literal on the right */
4100   if (AOP_TYPE(left) == AOP_LIT){
4101     operand *t = right;
4102     right = left;
4103     left = t;
4104   }
4105
4106   /* size is checked already == 4 */
4107 //  size = AOP_SIZE(result);
4108
4109   if (AOP_TYPE(right) == AOP_LIT) {
4110     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4111         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4112         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4113         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4114   } else {
4115     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4116         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4117         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4118         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4119   }
4120         
4121   pic16_genMult32X32_32(left, right,result);
4122 }
4123
4124
4125
4126 /*-----------------------------------------------------------------*/
4127 /* genMult - generates code for multiplication                     */
4128 /*-----------------------------------------------------------------*/
4129 static void genMult (iCode *ic)
4130 {
4131   operand *left = IC_LEFT(ic);
4132   operand *right = IC_RIGHT(ic);
4133   operand *result= IC_RESULT(ic);   
4134
4135     FENTRY;
4136         /* assign the amsops */
4137         pic16_aopOp (left,ic,FALSE);
4138         pic16_aopOp (right,ic,FALSE);
4139         pic16_aopOp (result,ic,TRUE);
4140
4141         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4142
4143         /* special cases first *
4144         * both are bits */
4145         if (AOP_TYPE(left) == AOP_CRY
4146                 && AOP_TYPE(right)== AOP_CRY) {
4147                 genMultbits(left,right,result);
4148           goto release ;
4149         }
4150
4151         /* if both are of size == 1 */
4152         if(AOP_SIZE(left) == 1
4153                 && AOP_SIZE(right) == 1) {
4154                 genMultOneByte(left,right,result);
4155           goto release ;
4156         }
4157
4158         /* if both are of size == 2 */
4159         if(AOP_SIZE(left) == 2
4160                 && AOP_SIZE(right) == 2) {
4161                 genMultOneWord(left, right, result);
4162           goto release;
4163         }
4164         
4165         /* if both are of size == 4 */
4166         if(AOP_SIZE(left) == 4
4167                 && AOP_SIZE(right) == 4) {
4168                 genMultOneLong(left, right, result);
4169           goto release;
4170         }
4171         
4172         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4173
4174
4175         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4176         /* should have been converted to function call */
4177         assert(0) ;
4178
4179 release :
4180         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4181         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4182         pic16_freeAsmop(result,NULL,ic,TRUE); 
4183 }
4184
4185 /*-----------------------------------------------------------------*/
4186 /* genDivbits :- division of bits                                  */
4187 /*-----------------------------------------------------------------*/
4188 static void genDivbits (operand *left, 
4189                         operand *right, 
4190                         operand *result)
4191 {
4192   char *l;
4193
4194     FENTRY;
4195     /* the result must be bit */    
4196     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4197     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4198
4199     MOVA(l);    
4200
4201     pic16_emitcode("div","ab");
4202     pic16_emitcode("rrc","a");
4203     pic16_aopPut(AOP(result),"c",0);
4204 }
4205
4206 /*-----------------------------------------------------------------*/
4207 /* genDivOneByte : 8 bit division                                  */
4208 /*-----------------------------------------------------------------*/
4209 static void genDivOneByte (operand *left,
4210                            operand *right,
4211                            operand *result)
4212 {
4213   sym_link *opetype = operandType(result);
4214   char *l ;
4215   symbol *lbl ;
4216   int size,offset;
4217
4218         /* result = divident / divisor
4219          * - divident may be a register or a literal,
4220          * - divisor may be a register or a literal,
4221          * so there are 3 cases (literal / literal is optimized
4222          * by the front-end) to handle.
4223          * In addition we must handle signed and unsigned, which
4224          * result in 6 final different cases -- VR */
4225
4226     FENTRY;
4227     
4228     size = AOP_SIZE(result) - 1;
4229     offset = 1;
4230     /* signed or unsigned */
4231     if (SPEC_USIGN(opetype)) {
4232       pCodeOp *pct1,    /* count */
4233                 *pct2,  /* reste */
4234                 *pct3;  /* temp */
4235       symbol *label1, *label2, *label3;;
4236
4237
4238         /* unsigned is easy */
4239
4240         pct1 = pic16_popGetTempReg(1);
4241         pct2 = pic16_popGetTempReg(1);
4242         pct3 = pic16_popGetTempReg(1);
4243         
4244         label1 = newiTempLabel(NULL);
4245         label2 = newiTempLabel(NULL);
4246         label3 = newiTempLabel(NULL);
4247
4248         /* the following algorithm is extracted from divuint.c */
4249
4250         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4251         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4252         
4253         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4254
4255         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4256         
4257         pic16_emitpLabel(label1->key);
4258         
4259         emitCLRC;
4260         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4261
4262
4263         emitCLRC;
4264         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4265         
4266
4267         emitSKPNC;
4268         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4269         
4270         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4271         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4272         
4273         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4274         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4275         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4276         
4277         pic16_emitpLabel( label3->key );
4278         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4279         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4280         
4281         
4282
4283         pic16_emitpLabel(label2->key);
4284         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4285         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4286         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4287         
4288         /* result is in wreg */
4289         if(AOP_TYPE(result) != AOP_ACC)
4290                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4291
4292         pic16_popReleaseTempReg( pct3, 1);
4293         pic16_popReleaseTempReg( pct2, 1);
4294         pic16_popReleaseTempReg( pct1, 1);
4295
4296         return ;
4297     }
4298
4299     /* signed is a little bit more difficult */
4300
4301     /* save the signs of the operands */
4302     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4303     MOVA(l);    
4304     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4305     pic16_emitcode("push","acc"); /* save it on the stack */
4306
4307     /* now sign adjust for both left & right */
4308     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4309     MOVA(l);       
4310     lbl = newiTempLabel(NULL);
4311     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4312     pic16_emitcode("cpl","a");   
4313     pic16_emitcode("inc","a");
4314     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4315     pic16_emitcode("mov","b,a");
4316
4317     /* sign adjust left side */
4318     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4319     MOVA(l);
4320
4321     lbl = newiTempLabel(NULL);
4322     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4323     pic16_emitcode("cpl","a");
4324     pic16_emitcode("inc","a");
4325     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4326
4327     /* now the division */
4328     pic16_emitcode("div","ab");
4329     /* we are interested in the lower order
4330     only */
4331     pic16_emitcode("mov","b,a");
4332     lbl = newiTempLabel(NULL);
4333     pic16_emitcode("pop","acc");   
4334     /* if there was an over flow we don't 
4335     adjust the sign of the result */
4336     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4337     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4338     CLRC;
4339     pic16_emitcode("clr","a");
4340     pic16_emitcode("subb","a,b");
4341     pic16_emitcode("mov","b,a");
4342     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4343
4344     /* now we are done */
4345     pic16_aopPut(AOP(result),"b",0);
4346     if(size > 0){
4347         pic16_emitcode("mov","c,b.7");
4348         pic16_emitcode("subb","a,acc");   
4349     }
4350     while (size--)
4351         pic16_aopPut(AOP(result),"a",offset++);
4352
4353 }
4354
4355 /*-----------------------------------------------------------------*/
4356 /* genDiv - generates code for division                            */
4357 /*-----------------------------------------------------------------*/
4358 static void genDiv (iCode *ic)
4359 {
4360     operand *left = IC_LEFT(ic);
4361     operand *right = IC_RIGHT(ic);
4362     operand *result= IC_RESULT(ic);   
4363
4364
4365         /* Division is a very lengthy algorithm, so it is better
4366          * to call support routines than inlining algorithm.
4367          * Division functions written here just in case someone
4368          * wants to inline and not use the support libraries -- VR */
4369
4370     FENTRY;
4371     
4372     /* assign the amsops */
4373     pic16_aopOp (left,ic,FALSE);
4374     pic16_aopOp (right,ic,FALSE);
4375     pic16_aopOp (result,ic,TRUE);
4376
4377     /* special cases first */
4378     /* both are bits */
4379     if (AOP_TYPE(left) == AOP_CRY &&
4380         AOP_TYPE(right)== AOP_CRY) {
4381         genDivbits(left,right,result);
4382         goto release ;
4383     }
4384
4385     /* if both are of size == 1 */
4386     if (AOP_SIZE(left) == 1 &&
4387         AOP_SIZE(right) == 1 ) {
4388         genDivOneByte(left,right,result);
4389         goto release ;
4390     }
4391
4392     /* should have been converted to function call */
4393     assert(0);
4394 release :
4395     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4396     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4397     pic16_freeAsmop(result,NULL,ic,TRUE); 
4398 }
4399
4400 /*-----------------------------------------------------------------*/
4401 /* genModbits :- modulus of bits                                   */
4402 /*-----------------------------------------------------------------*/
4403 static void genModbits (operand *left, 
4404                         operand *right, 
4405                         operand *result)
4406 {
4407   char *l;
4408
4409     FENTRY;  
4410     
4411     werror(W_POSSBUG2, __FILE__, __LINE__);
4412     /* the result must be bit */    
4413     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4414     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4415
4416     MOVA(l);       
4417
4418     pic16_emitcode("div","ab");
4419     pic16_emitcode("mov","a,b");
4420     pic16_emitcode("rrc","a");
4421     pic16_aopPut(AOP(result),"c",0);
4422 }
4423
4424 /*-----------------------------------------------------------------*/
4425 /* genModOneByte : 8 bit modulus                                   */
4426 /*-----------------------------------------------------------------*/
4427 static void genModOneByte (operand *left,
4428                            operand *right,
4429                            operand *result)
4430 {
4431   sym_link *opetype = operandType(result);
4432   char *l ;
4433   symbol *lbl ;
4434
4435     FENTRY;
4436     werror(W_POSSBUG2, __FILE__, __LINE__);
4437
4438     /* signed or unsigned */
4439     if (SPEC_USIGN(opetype)) {
4440         /* unsigned is easy */
4441         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4442         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4443         MOVA(l);    
4444         pic16_emitcode("div","ab");
4445         pic16_aopPut(AOP(result),"b",0);
4446         return ;
4447     }
4448
4449     /* signed is a little bit more difficult */
4450
4451     /* save the signs of the operands */
4452     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4453     MOVA(l);
4454
4455     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4456     pic16_emitcode("push","acc"); /* save it on the stack */
4457
4458     /* now sign adjust for both left & right */
4459     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4460     MOVA(l);
4461
4462     lbl = newiTempLabel(NULL);
4463     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4464     pic16_emitcode("cpl","a");   
4465     pic16_emitcode("inc","a");
4466     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4467     pic16_emitcode("mov","b,a"); 
4468
4469     /* sign adjust left side */
4470     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4471     MOVA(l);
4472
4473     lbl = newiTempLabel(NULL);
4474     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4475     pic16_emitcode("cpl","a");   
4476     pic16_emitcode("inc","a");
4477     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4478
4479     /* now the multiplication */
4480     pic16_emitcode("div","ab");
4481     /* we are interested in the lower order
4482     only */
4483     lbl = newiTempLabel(NULL);
4484     pic16_emitcode("pop","acc");   
4485     /* if there was an over flow we don't 
4486     adjust the sign of the result */
4487     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4488     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4489     CLRC ;
4490     pic16_emitcode("clr","a");
4491     pic16_emitcode("subb","a,b");
4492     pic16_emitcode("mov","b,a");
4493     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4494
4495     /* now we are done */
4496     pic16_aopPut(AOP(result),"b",0);
4497
4498 }
4499
4500 /*-----------------------------------------------------------------*/
4501 /* genMod - generates code for division                            */
4502 /*-----------------------------------------------------------------*/
4503 static void genMod (iCode *ic)
4504 {
4505   operand *left = IC_LEFT(ic);
4506   operand *right = IC_RIGHT(ic);
4507   operand *result= IC_RESULT(ic);  
4508
4509     FENTRY;
4510     
4511     /* assign the amsops */
4512     pic16_aopOp (left,ic,FALSE);
4513     pic16_aopOp (right,ic,FALSE);
4514     pic16_aopOp (result,ic,TRUE);
4515
4516     /* special cases first */
4517     /* both are bits */
4518     if (AOP_TYPE(left) == AOP_CRY &&
4519         AOP_TYPE(right)== AOP_CRY) {
4520         genModbits(left,right,result);
4521         goto release ;
4522     }
4523
4524     /* if both are of size == 1 */
4525     if (AOP_SIZE(left) == 1 &&
4526         AOP_SIZE(right) == 1 ) {
4527         genModOneByte(left,right,result);
4528         goto release ;
4529     }
4530
4531     /* should have been converted to function call */
4532     assert(0);
4533
4534 release :
4535     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4536     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4537     pic16_freeAsmop(result,NULL,ic,TRUE); 
4538 }
4539
4540 /*-----------------------------------------------------------------*/
4541 /* genIfxJump :- will create a jump depending on the ifx           */
4542 /*-----------------------------------------------------------------*/
4543 /*
4544   note: May need to add parameter to indicate when a variable is in bit space.
4545 */
4546 static void genIfxJump (iCode *ic, char *jval)
4547 {
4548   FENTRY;
4549   
4550     /* if true label then we jump if condition
4551     supplied is true */
4552     if ( IC_TRUE(ic) ) {
4553
4554         if(strcmp(jval,"a") == 0)
4555           emitSKPZ;
4556         else if (strcmp(jval,"c") == 0)
4557           emitSKPNC;
4558         else {
4559           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4560           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4561         }
4562
4563         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4564         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4565
4566     }
4567     else {
4568         /* false label is present */
4569         if(strcmp(jval,"a") == 0)
4570           emitSKPNZ;
4571         else if (strcmp(jval,"c") == 0)
4572           emitSKPC;
4573         else {
4574           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4575           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4576         }
4577
4578         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4579         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4580
4581     }
4582
4583
4584     /* mark the icode as generated */
4585     ic->generated = 1;
4586 }
4587
4588 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4589 {
4590   FENTRY;
4591   
4592     /* if true label then we jump if condition
4593     supplied is true */
4594     if ( IC_TRUE(ic) ) {
4595       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4596       pic16_emitpcode(POC_BTFSC, jop);
4597
4598       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4599       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4600
4601     } else {
4602       /* false label is present */
4603       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4604       pic16_emitpcode(POC_BTFSS, jop);
4605           
4606       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4607       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4608     }
4609
4610
4611     /* mark the icode as generated */
4612     ic->generated = 1;
4613 }
4614
4615 #if 0
4616 // not needed ATM
4617
4618 /*-----------------------------------------------------------------*/
4619 /* genSkip                                                         */
4620 /*-----------------------------------------------------------------*/
4621 static void genSkip(iCode *ifx,int status_bit)
4622 {
4623   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4624   if(!ifx)
4625     return;
4626
4627   if ( IC_TRUE(ifx) ) {
4628     switch(status_bit) {
4629     case 'z':
4630       emitSKPNZ;
4631       break;
4632
4633     case 'c':
4634       emitSKPNC;
4635       break;
4636
4637     case 'd':
4638       emitSKPDC;
4639       break;
4640
4641     }
4642
4643     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4644     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4645
4646   } else {
4647
4648     switch(status_bit) {
4649
4650     case 'z':
4651       emitSKPZ;
4652       break;
4653
4654     case 'c':
4655       emitSKPC;
4656       break;
4657
4658     case 'd':
4659       emitSKPDC;
4660       break;
4661     }
4662     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4663     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4664
4665   }
4666
4667 }
4668 #endif
4669
4670 /*-----------------------------------------------------------------*/
4671 /* genSkipc                                                        */
4672 /*-----------------------------------------------------------------*/
4673 static void genSkipc(resolvedIfx *rifx)
4674 {
4675   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4676   
4677   if(!rifx)
4678     return;
4679
4680   if(rifx->condition)
4681     emitSKPC;
4682   else
4683     emitSKPNC;
4684
4685   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4686   rifx->generated = 1;
4687 }
4688
4689 #if !(USE_SIMPLE_GENCMP)
4690 /*-----------------------------------------------------------------*/
4691 /* genSkipz2                                                       */
4692 /*-----------------------------------------------------------------*/
4693 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4694 {
4695   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4696   
4697   if(!rifx)
4698     return;
4699
4700   if( (rifx->condition ^ invert_condition) & 1)
4701     emitSKPZ;
4702   else
4703     emitSKPNZ;
4704
4705   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4706   rifx->generated = 1;
4707 }
4708 #endif
4709
4710 #if 0
4711 /*-----------------------------------------------------------------*/
4712 /* genSkipz                                                        */
4713 /*-----------------------------------------------------------------*/
4714 static void genSkipz(iCode *ifx, int condition)
4715 {
4716   if(!ifx)
4717     return;
4718
4719   if(condition)
4720     emitSKPNZ;
4721   else
4722     emitSKPZ;
4723
4724   if ( IC_TRUE(ifx) )
4725     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4726   else
4727     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4728
4729   if ( IC_TRUE(ifx) )
4730     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4731   else
4732     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4733
4734 }
4735 #endif
4736
4737 #if !(USE_SIMPLE_GENCMP)
4738 /*-----------------------------------------------------------------*/
4739 /* genSkipCond                                                     */
4740 /*-----------------------------------------------------------------*/
4741 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4742 {
4743   if(!rifx)
4744     return;
4745
4746   if(rifx->condition)
4747     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4748   else
4749     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4750
4751
4752   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4753   rifx->generated = 1;
4754 }
4755 #endif
4756
4757 #if 0
4758 /*-----------------------------------------------------------------*/
4759 /* genChkZeroes :- greater or less than comparison                 */
4760 /*     For each byte in a literal that is zero, inclusive or the   */
4761 /*     the corresponding byte in the operand with W                */
4762 /*     returns true if any of the bytes are zero                   */
4763 /*-----------------------------------------------------------------*/
4764 static int genChkZeroes(operand *op, int lit,  int size)
4765 {
4766
4767   int i;
4768   int flag =1;
4769
4770   while(size--) {
4771     i = (lit >> (size*8)) & 0xff;
4772
4773     if(i==0) {
4774       if(flag) 
4775         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4776       else
4777         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4778       flag = 0;
4779     }
4780   }
4781
4782   return (flag==0);
4783 }
4784 #endif
4785
4786 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4787 #define DEBUGpc(fmt,...)  DEBUGpic16_emitcode("; =:=", "%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
4788 #endif
4789 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
4790 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE || AOP_TYPE(x) == AOP_STA)
4791
4792 /*-----------------------------------------------------------------*/
4793 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4794 /*                  aop (if it's NOT a literal) or from lit (if    */
4795 /*                  aop is a literal)                              */
4796 /*-----------------------------------------------------------------*/
4797 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4798   if (aop->type == AOP_LIT) {
4799     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4800   } else {
4801     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4802   }
4803 }
4804
4805 /*-----------------------------------------------------------------*/
4806 /* genCmp :- greater or less than comparison                       */
4807 /*-----------------------------------------------------------------*/
4808
4809 #if USE_SIMPLE_GENCMP
4810
4811 /* genCmp performs a left < right comparison, stores
4812  * the outcome in result (if != NULL) and generates
4813  * control flow code for the ifx (if != NULL).
4814  *
4815  * This version leaves in sequences like
4816  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4817  * which should be optmized by the peephole
4818  * optimizer - RN 2005-01-01 */
4819 static void genCmp (operand *left,operand *right,
4820                     operand *result, iCode *ifx, int sign)
4821 {
4822   resolvedIfx rIfx;
4823   int size;
4824   int offs;
4825   symbol *templbl;
4826   operand *dummy;
4827   unsigned long lit;
4828   unsigned long mask;
4829   int performedLt;
4830
4831   FENTRY;
4832   
4833   assert (AOP_SIZE(left) == AOP_SIZE(right));
4834   assert (left && right);
4835
4836   size = AOP_SIZE(right) - 1;
4837   mask = (0x100UL << (size*8)) - 1;
4838   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4839   performedLt = 1;
4840   templbl = NULL;
4841   lit = 0;
4842   
4843   resolveIfx (&rIfx, ifx);
4844
4845   /**********************************************************************
4846    * handle bits - bit compares are promoted to int compares seemingly! *
4847    **********************************************************************/
4848 #if 0
4849   // THIS IS COMPLETELY UNTESTED!
4850   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4851     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4852     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4853     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4854
4855     emitSETC;
4856     // 1 < {0,1} is false --> clear C by skipping the next instruction
4857     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4858     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4859     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4860     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4861     emitCLRC; // only skipped for left=0 && right=1
4862
4863     goto correct_result_in_carry;
4864   } // if
4865 #endif
4866
4867   /*************************************************
4868    * make sure that left is register (or the like) *
4869    *************************************************/
4870   if (!isAOP_REGlike(left)) {
4871     #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4872     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4873     #endif
4874     assert (isAOP_LIT(left));
4875     assert (isAOP_REGlike(right));
4876     // swap left and right
4877     // left < right <==> right > left <==> (right >= left + 1)
4878     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4879
4880     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4881       // MAXVALUE < right? always false
4882       if (performedLt) emitCLRC; else emitSETC;
4883       goto correct_result_in_carry;
4884     } // if
4885
4886     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4887     // that's we handled it above.
4888     lit++;
4889
4890     dummy = left;
4891     left = right;
4892     right = dummy;
4893
4894     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
4895   } else if (isAOP_LIT(right)) {
4896     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4897   } // if
4898
4899   assert (isAOP_REGlike(left)); // left must be register or the like
4900   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4901
4902   /*************************************************
4903    * special cases go here                         *
4904    *************************************************/
4905
4906   if (isAOP_LIT(right)) {
4907     if (!sign) {
4908       // unsigned comparison to a literal
4909       #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4910       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4911       #endif
4912       if (lit == 0) {
4913         // unsigned left < 0? always false
4914         if (performedLt) emitCLRC; else emitSETC;
4915         goto correct_result_in_carry;
4916       }
4917     } else {
4918       // signed comparison to a literal
4919       #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4920       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4921       #endif
4922       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4923         // signed left < 0x80000000? always false
4924         if (performedLt) emitCLRC; else emitSETC;
4925         goto correct_result_in_carry;
4926       } else if (lit == 0) {
4927         // compare left < 0; set CARRY if SIGNBIT(left) is set
4928         if (performedLt) emitSETC; else emitCLRC;
4929         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4930         if (performedLt) emitCLRC; else emitSETC;
4931         goto correct_result_in_carry;
4932       }
4933     } // if (!sign)
4934   } // right is literal
4935
4936   /*************************************************
4937    * perform a general case comparison             *
4938    * make sure we get CARRY==1 <==> left >= right  *
4939    *************************************************/
4940   // compare most significant bytes
4941   //DEBUGpc ("comparing bytes at offset %d", size);
4942   if (!sign) {
4943     // unsigned comparison
4944     mov2w_regOrLit (AOP(right), lit, size);
4945     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
4946   } else {
4947     // signed comparison
4948     // (add 2^n to both operands then perform an unsigned comparison)
4949     if (isAOP_LIT(right)) {
4950       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4951       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4952
4953       if (litbyte == 0x80) {
4954         // left >= 0x80 -- always true, but more bytes to come
4955         pic16_mov2w (AOP(left), size);
4956         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
4957         emitSETC;
4958       } else {
4959         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4960         pic16_mov2w (AOP(left), size);
4961         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4962         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4963       } // if
4964     } else {
4965       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
4966       //pCodeOp *pctemp = pic16_popGetTempReg(1);
4967       pic16_mov2w (AOP(left), size);
4968       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4969       pic16_emitpcode (POC_MOVWF, pctemp);
4970       pic16_mov2w (AOP(right), size);
4971       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4972       pic16_emitpcode (POC_SUBFW, pctemp);
4973       //pic16_popReleaseTempReg(pctemp, 1);
4974     }
4975   } // if (!sign)
4976
4977   // compare remaining bytes (treat as unsigned case from above)
4978   templbl = newiTempLabel ( NULL );
4979   offs = size;
4980   while (offs--) {
4981     //DEBUGpc ("comparing bytes at offset %d", offs);
4982     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
4983     mov2w_regOrLit (AOP(right), lit, offs);
4984     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
4985   } // while (offs)
4986   pic16_emitpLabel (templbl->key);
4987   goto result_in_carry;
4988
4989 result_in_carry:
4990   
4991   /****************************************************
4992    * now CARRY contains the result of the comparison: *
4993    * SUBWF sets CARRY iff                             *
4994    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4995    * (F=left, W=right)
4996    ****************************************************/
4997
4998   if (performedLt) {
4999     if (result && AOP_TYPE(result) != AOP_CRY) {
5000       // value will be stored
5001       emitTOGC;
5002     } else {
5003       // value wil only be used in the following genSkipc()
5004       rIfx.condition ^= 1;
5005     }
5006   } // if
5007
5008 correct_result_in_carry:
5009
5010   // assign result to variable (if neccessary)
5011   if (result && AOP_TYPE(result) != AOP_CRY) {
5012     //DEBUGpc ("assign result");
5013     size = AOP_SIZE(result);
5014     while (size--) {
5015       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5016     } // while
5017     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5018   } // if (result)
5019
5020   // perform conditional jump
5021   // genSkipc branches to rifx->label if (rifx->condition != CARRY)
5022   if (ifx) {
5023     //DEBUGpc ("generate control flow");
5024     rIfx.condition ^= 1;
5025     genSkipc (&rIfx);
5026     ifx->generated = 1;
5027   } // if
5028 }
5029
5030 #elif 1
5031                 /* { */
5032       /* original code */
5033 static void genCmp (operand *left,operand *right,
5034                     operand *result, iCode *ifx, int sign)
5035 {
5036   int size; //, offset = 0 ;
5037   unsigned long lit = 0L,i = 0;
5038   resolvedIfx rFalseIfx;
5039   //  resolvedIfx rTrueIfx;
5040   symbol *truelbl;
5041   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5042 /*
5043   if(ifx) {
5044     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5045     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5046   }
5047 */
5048
5049   FENTRY;
5050   
5051   resolveIfx(&rFalseIfx,ifx);
5052   truelbl  = newiTempLabel(NULL);
5053   size = max(AOP_SIZE(left),AOP_SIZE(right));
5054
5055   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5056
5057 #define _swapp
5058
5059   /* if literal is on the right then swap with left */
5060   if ((AOP_TYPE(right) == AOP_LIT)) {
5061     operand *tmp = right ;
5062     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5063     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5064 #ifdef _swapp
5065
5066     lit = (lit - 1) & mask;
5067     right = left;
5068     left = tmp;
5069     rFalseIfx.condition ^= 1;
5070 #endif
5071
5072   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5073     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5074   }
5075
5076
5077   //if(IC_TRUE(ifx) == NULL)
5078   /* if left & right are bit variables */
5079   if (AOP_TYPE(left) == AOP_CRY &&
5080       AOP_TYPE(right) == AOP_CRY ) {
5081     assert (0 && "bit variables used in genCmp");
5082     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5083     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5084   } else {
5085     /* subtract right from left if at the
5086        end the carry flag is set then we know that
5087        left is greater than right */
5088
5089     symbol *lbl  = newiTempLabel(NULL);
5090
5091 #if 0
5092         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5093                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5094 #endif
5095
5096 #ifndef _swapp
5097     if(AOP_TYPE(right) == AOP_LIT) {
5098
5099       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5100
5101       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5102
5103       /* special cases */
5104
5105       if(lit == 0) {
5106
5107         if(sign != 0) 
5108           genSkipCond(&rFalseIfx,left,size-1,7);
5109         else 
5110           /* no need to compare to 0...*/
5111           /* NOTE: this is a de-generate compare that most certainly 
5112            *       creates some dead code. */
5113           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5114
5115         if(ifx) ifx->generated = 1;
5116         return;
5117
5118       }
5119       size--;
5120
5121       if(size == 0) {
5122         //i = (lit >> (size*8)) & 0xff;
5123         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5124         
5125         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5126
5127         i = ((0-lit) & 0xff);
5128         if(sign) {
5129           if( i == 0x81) { 
5130             /* lit is 0x7f, all signed chars are less than
5131              * this except for 0x7f itself */
5132             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5133             genSkipz2(&rFalseIfx,0);
5134           } else {
5135             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5136             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5137             genSkipc(&rFalseIfx);
5138           }
5139
5140         } else {
5141           if(lit == 1) {
5142             genSkipz2(&rFalseIfx,1);
5143           } else {
5144             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5145             genSkipc(&rFalseIfx);
5146           }
5147         }
5148
5149         if(ifx) ifx->generated = 1;
5150         return;
5151       }
5152
5153       /* chars are out of the way. now do ints and longs */
5154
5155
5156       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5157         
5158       /* special cases */
5159
5160       if(sign) {
5161
5162         if(lit == 0) {
5163           genSkipCond(&rFalseIfx,left,size,7);
5164           if(ifx) ifx->generated = 1;
5165           return;
5166         }
5167
5168         if(lit <0x100) {
5169           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5170
5171           //rFalseIfx.condition ^= 1;
5172           //genSkipCond(&rFalseIfx,left,size,7);
5173           //rFalseIfx.condition ^= 1;
5174
5175           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5176           if(rFalseIfx.condition)
5177             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5178           else
5179             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5180
5181           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5182           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5183           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5184
5185           while(size > 1)
5186             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5187
5188           if(rFalseIfx.condition) {
5189             emitSKPZ;
5190             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5191
5192           } else {
5193             emitSKPNZ;
5194           }
5195
5196           genSkipc(&rFalseIfx);
5197           pic16_emitpLabel(truelbl->key);
5198           if(ifx) ifx->generated = 1;
5199           return;
5200
5201         }
5202
5203         if(size == 1) {
5204
5205           if( (lit & 0xff) == 0) {
5206             /* lower byte is zero */
5207             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5208             i = ((lit >> 8) & 0xff) ^0x80;
5209             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5210             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5211             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5212             genSkipc(&rFalseIfx);
5213
5214
5215             if(ifx) ifx->generated = 1;
5216             return;
5217
5218           }
5219         } else {
5220           /* Special cases for signed longs */
5221           if( (lit & 0xffffff) == 0) {
5222             /* lower byte is zero */
5223             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5224             i = ((lit >> 8*3) & 0xff) ^0x80;
5225             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5226             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5227             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5228             genSkipc(&rFalseIfx);
5229
5230
5231             if(ifx) ifx->generated = 1;
5232             return;
5233
5234           }
5235
5236         }
5237
5238
5239         if(lit & (0x80 << (size*8))) {
5240           /* lit is negative */
5241           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5242
5243           //genSkipCond(&rFalseIfx,left,size,7);
5244
5245           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5246
5247           if(rFalseIfx.condition)
5248             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5249           else
5250             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5251
5252
5253         } else {
5254           /* lit is positive */
5255           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5256           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5257           if(rFalseIfx.condition)
5258             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5259           else
5260             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5261
5262         }
5263
5264         /*
5265           This works, but is only good for ints.
5266           It also requires a "known zero" register.
5267           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5268           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5269           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5270           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5271           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5272           genSkipc(&rFalseIfx);
5273
5274           pic16_emitpLabel(truelbl->key);
5275           if(ifx) ifx->generated = 1;
5276           return;
5277         **/
5278           
5279         /* There are no more special cases, so perform a general compare */
5280   
5281         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5282         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5283
5284         while(size--) {
5285
5286           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5287           emitSKPNZ;
5288           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5289         }
5290         //rFalseIfx.condition ^= 1;
5291         genSkipc(&rFalseIfx);
5292
5293         pic16_emitpLabel(truelbl->key);
5294
5295         if(ifx) ifx->generated = 1;
5296         return;
5297
5298
5299       }
5300
5301
5302       /* sign is out of the way. So now do an unsigned compare */
5303       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5304
5305
5306       /* General case - compare to an unsigned literal on the right.*/
5307
5308       i = (lit >> (size*8)) & 0xff;
5309       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5310       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5311       while(size--) {
5312         i = (lit >> (size*8)) & 0xff;
5313
5314         if(i) {
5315           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5316           emitSKPNZ;
5317           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5318         } else {
5319           /* this byte of the lit is zero, 
5320            *if it's not the last then OR in the variable */
5321           if(size)
5322             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5323         }
5324       }
5325
5326
5327       pic16_emitpLabel(lbl->key);
5328 //      pic16_emitpLabel(truelbl->key);
5329       //if(emitFinalCheck)
5330       genSkipc(&rFalseIfx);
5331       if(sign)
5332         pic16_emitpLabel(truelbl->key);
5333
5334       if(ifx) ifx->generated = 1;
5335       return;
5336
5337
5338     }
5339 #endif  // _swapp
5340
5341     if(AOP_TYPE(left) == AOP_LIT) {
5342       //symbol *lbl = newiTempLabel(NULL);
5343
5344       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5345
5346
5347       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5348
5349       /* Special cases */
5350       if((lit == 0) && (sign == 0)){
5351
5352         size--;
5353         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5354         while(size) 
5355           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5356
5357         genSkipz2(&rFalseIfx,0);
5358         if(ifx) ifx->generated = 1;
5359         return;
5360       }
5361
5362       if(size==1) {
5363         /* Special cases */
5364         lit &= 0xff;
5365         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5366           /* degenerate compare can never be true */
5367           if(rFalseIfx.condition == 0)
5368             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5369
5370           if(ifx) ifx->generated = 1;
5371           return;
5372         }
5373
5374         if(sign) {
5375           /* signed comparisons to a literal byte */
5376
5377           int lp1 = (lit+1) & 0xff;
5378
5379           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5380           switch (lp1) {
5381           case 0:
5382             rFalseIfx.condition ^= 1;
5383             genSkipCond(&rFalseIfx,right,0,7);
5384             break;
5385           case 0x7f:
5386             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5387             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5388             genSkipz2(&rFalseIfx,1);
5389             break;
5390           default:
5391             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5392             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5393             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5394             rFalseIfx.condition ^= 1;
5395             genSkipc(&rFalseIfx);
5396             break;
5397           }
5398         } else {
5399           /* unsigned comparisons to a literal byte */
5400
5401           switch(lit & 0xff ) {
5402           case 0:
5403             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5404             genSkipz2(&rFalseIfx,0);
5405             break;
5406           case 0x7f:
5407             rFalseIfx.condition ^= 1;
5408             genSkipCond(&rFalseIfx,right,0,7);
5409             break;
5410
5411           default:
5412             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5413             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5414             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5415             rFalseIfx.condition ^= 1;
5416             if (AOP_TYPE(result) == AOP_CRY)
5417               genSkipc(&rFalseIfx);
5418             else {
5419               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5420               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5421             }         
5422             break;
5423           }
5424         }
5425
5426         if(ifx) ifx->generated = 1;
5427         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5428                 goto check_carry;
5429         return;
5430
5431       } else {
5432
5433         /* Size is greater than 1 */
5434
5435         if(sign) {
5436           int lp1 = lit+1;
5437
5438           size--;
5439
5440           if(lp1 == 0) {
5441             /* this means lit = 0xffffffff, or -1 */
5442
5443
5444             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5445             rFalseIfx.condition ^= 1;
5446             genSkipCond(&rFalseIfx,right,size,7);
5447             if(ifx) ifx->generated = 1;
5448
5449             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5450               goto check_carry;
5451
5452             return;
5453           }
5454
5455           if(lit == 0) {
5456             int s = size;
5457
5458             if(rFalseIfx.condition) {
5459               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5460               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5461             }
5462
5463             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5464             while(size--)
5465               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5466
5467
5468             emitSKPZ;
5469             if(rFalseIfx.condition) {
5470               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5471               pic16_emitpLabel(truelbl->key);
5472             }else {
5473               rFalseIfx.condition ^= 1;
5474               genSkipCond(&rFalseIfx,right,s,7);
5475             }
5476
5477             if(ifx) ifx->generated = 1;
5478
5479             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5480               goto check_carry;
5481
5482             return;
5483           }
5484
5485           if((size == 1) &&  (0 == (lp1&0xff))) {
5486             /* lower byte of signed word is zero */
5487             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5488             i = ((lp1 >> 8) & 0xff) ^0x80;
5489             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5490             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5491             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5492
5493             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5494               emitTOGC;
5495               if(ifx) ifx->generated = 1;
5496               goto check_carry;
5497             } else {
5498               rFalseIfx.condition ^= 1;
5499               genSkipc(&rFalseIfx);
5500               if(ifx) ifx->generated = 1;
5501             }
5502
5503             return;
5504           }
5505
5506           if(lit & (0x80 << (size*8))) {
5507             /* Lit is less than zero */
5508             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5509             //rFalseIfx.condition ^= 1;
5510             //genSkipCond(&rFalseIfx,left,size,7);
5511             //rFalseIfx.condition ^= 1;
5512             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5513             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5514
5515             if(rFalseIfx.condition)
5516               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5517             else
5518               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5519
5520
5521           } else {
5522             /* Lit is greater than or equal to zero */
5523             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5524             //rFalseIfx.condition ^= 1;
5525             //genSkipCond(&rFalseIfx,right,size,7);
5526             //rFalseIfx.condition ^= 1;
5527
5528             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5529             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5530
5531             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5532             if(rFalseIfx.condition)
5533               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5534             else
5535               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5536
5537           }
5538
5539           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5540           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5541
5542           while(size--) {
5543
5544             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5545             emitSKPNZ;
5546             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5547           }
5548           rFalseIfx.condition ^= 1;
5549           //rFalseIfx.condition = 1;
5550           genSkipc(&rFalseIfx);
5551
5552           pic16_emitpLabel(truelbl->key);
5553
5554           if(ifx) ifx->generated = 1;
5555
5556
5557           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5558             goto check_carry;
5559
5560           return;
5561           // end of if (sign)
5562         } else {
5563
5564           /* compare word or long to an unsigned literal on the right.*/
5565
5566
5567           size--;
5568           if(lit < 0xff) {
5569             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5570             switch (lit) {
5571             case 0:
5572               break; /* handled above */
5573 /*
5574             case 0xff:
5575               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5576               while(size--)
5577                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5578               genSkipz2(&rFalseIfx,0);
5579               break;
5580 */
5581             default:
5582               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5583               while(--size)
5584                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5585
5586               emitSKPZ;
5587               if(rFalseIfx.condition)
5588                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5589               else
5590                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5591
5592
5593               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5594               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5595
5596               rFalseIfx.condition ^= 1;
5597               genSkipc(&rFalseIfx);
5598             }
5599
5600             pic16_emitpLabel(truelbl->key);
5601
5602             if(ifx) ifx->generated = 1;
5603
5604             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5605               goto check_carry;
5606
5607             return;
5608           }
5609
5610
5611           lit++;
5612           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5613           i = (lit >> (size*8)) & 0xff;
5614
5615           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5616           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5617
5618           while(size--) {
5619             i = (lit >> (size*8)) & 0xff;
5620
5621             if(i) {
5622               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5623               emitSKPNZ;
5624               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5625             } else {
5626               /* this byte of the lit is zero, 
5627                * if it's not the last then OR in the variable */
5628               if(size)
5629                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5630             }
5631           }
5632
5633
5634           pic16_emitpLabel(lbl->key);
5635
5636           rFalseIfx.condition ^= 1;
5637
5638           genSkipc(&rFalseIfx);
5639         }
5640
5641         if(sign)
5642           pic16_emitpLabel(truelbl->key);
5643         if(ifx) ifx->generated = 1;
5644
5645             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5646               goto check_carry;
5647
5648         return;
5649       }
5650     }
5651     /* Compare two variables */
5652
5653     DEBUGpic16_emitcode(";sign","%d",sign);
5654
5655     size--;
5656     if(sign) {
5657       /* Sigh. thus sucks... */
5658       if(size) {
5659         pCodeOp *pctemp;
5660         
5661         pctemp = pic16_popGetTempReg(1);
5662         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5663         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5664         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5665         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5666         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5667         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5668         pic16_popReleaseTempReg(pctemp, 1);
5669       } else {
5670         /* Signed char comparison */
5671         /* Special thanks to Nikolai Golovchenko for this snippet */
5672         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5673         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5674         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5675         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5676         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5677         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5678
5679         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5680         genSkipc(&rFalseIfx);
5681           
5682         if(ifx) ifx->generated = 1;
5683
5684             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5685               goto check_carry;
5686
5687         return;
5688       }
5689
5690     } else {
5691
5692       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5693       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5694     }
5695
5696
5697     /* The rest of the bytes of a multi-byte compare */
5698     while (size) {
5699
5700       emitSKPZ;
5701       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5702       size--;
5703
5704       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5705       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5706
5707
5708     }
5709
5710     pic16_emitpLabel(lbl->key);
5711
5712     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5713     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5714         (AOP_TYPE(result) == AOP_REG)) {
5715       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5716       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5717     } else {
5718       genSkipc(&rFalseIfx);
5719     }         
5720     //genSkipc(&rFalseIfx);
5721     if(ifx) ifx->generated = 1;
5722
5723
5724             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5725               goto check_carry;
5726
5727     return;
5728
5729   }
5730
5731 check_carry:
5732   if ((AOP_TYPE(result) != AOP_CRY) 
5733         && AOP_SIZE(result)) {
5734     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5735
5736     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5737
5738     pic16_outBitC(result);
5739   } else {
5740     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5741     /* if the result is used in the next
5742        ifx conditional branch then generate
5743        code a little differently */
5744     if (ifx )
5745       genIfxJump (ifx,"c");
5746     else
5747       pic16_outBitC(result);
5748     /* leave the result in acc */
5749   }
5750
5751 }
5752
5753 #else   /* old version of genCmp() */   /* } else { */
5754
5755 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5756 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5757         operand *result, int offset, int invert_op)
5758 {
5759   /* add code here */
5760   
5761   /* check condition, > or < ?? */
5762   if(rIfx->condition != 0)invert_op ^= 1;
5763   
5764   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5765
5766   if(!ifx)invert_op ^= 1;
5767
5768   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5769       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5770   
5771   /* do selection */
5772   if(!invert_op)return POC_CPFSGT;
5773   else return POC_CPFSLT;
5774 }
5775
5776 static int compareAopfirstpass=1;
5777
5778 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5779             operand *oper, int offset, operand *result,
5780             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5781             symbol *tlbl)
5782 {
5783   int op;
5784   symbol *truelbl;
5785
5786   /* invert if there is a result to be loaded, in order to fit,
5787    * SETC/CLRC sequence */
5788   if(AOP_SIZE(result))invert_op ^= 1;
5789
5790 //  if(sign && !offset)invert_op ^= 1;
5791   
5792 //  if(sign)invert_op ^= 1;
5793   
5794   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5795
5796   if(AOP_SIZE(result) && compareAopfirstpass) {
5797     if(!ifx) {
5798       if(pcop2)
5799         pic16_emitpcode(POC_SETF, pcop2);
5800       else
5801         emitSETC;
5802     } else {
5803       if(pcop2)
5804         pic16_emitpcode(POC_CLRF, pcop2);
5805       else
5806         emitCLRC;
5807     }
5808   }
5809
5810   compareAopfirstpass = 0;
5811
5812       /* there is a bug when comparing operands with size > 1,
5813        * because higher bytes can be equal and test should be performed
5814        * to the next lower byte, current algorithm, considers operands
5815        * inequal in these cases! -- VR 20041107 */
5816
5817     
5818   if(pcop)
5819     pic16_emitpcode(op, pcop);
5820   else
5821     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5822
5823
5824   if((!sign || !offset) && AOP_SIZE(result)) {
5825     if(!ifx) {
5826       if(pcop2)
5827         pic16_emitpcode(POC_CLRF, pcop2);
5828         else
5829         emitCLRC;
5830     } else {
5831       if(pcop2)
5832         pic16_emitpcode(POC_SETF, pcop2);
5833       else
5834         emitSETC;
5835     }
5836     
5837     /* don't emit final branch (offset == 0) */
5838     if(offset) {
5839
5840       if(pcop2)
5841         pic16_emitpcode(POC_RRCF, pcop2);
5842
5843       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5844     }
5845   } else {
5846     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5847       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5848             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5849
5850       truelbl = newiTempLabel( NULL );
5851       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5852       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5853         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5854       else
5855         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5856       pic16_emitpLabel(truelbl->key);
5857     } else {
5858       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5859     }
5860   }
5861 }
5862
5863
5864   
5865
5866 #if 1   /* { */
5867 static void genCmp (operand *left, operand *right,
5868                     operand *result, iCode *ifx, int sign)
5869 {
5870   int size, cmpop=1;
5871   long lit = 0L;
5872   resolvedIfx rFalseIfx;
5873   symbol *falselbl, *tlbl;
5874
5875     FENTRY;
5876     
5877     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5878
5879     resolveIfx(&rFalseIfx, ifx);
5880     size = max(AOP_SIZE(left), AOP_SIZE(right));
5881     
5882     /* if left & right are bit variables */
5883     if(AOP_TYPE(left) == AOP_CRY
5884       && AOP_TYPE(right) == AOP_CRY ) {
5885
5886         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5887         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5888         
5889         werror(W_POSSBUG2, __FILE__, __LINE__);
5890         exit(-1);
5891     }
5892     
5893     /* if literal is on the right then swap with left */
5894     if((AOP_TYPE(right) == AOP_LIT)) {
5895       operand *tmp = right ;
5896 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
5897
5898         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5899
5900 //      lit = (lit - 1) & mask;
5901         right = left;
5902         left = tmp;
5903         rFalseIfx.condition ^= 1;               /* reverse compare */
5904     } else
5905     if ((AOP_TYPE(left) == AOP_LIT)) {
5906       /* float compares are handled by support functions */
5907       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5908     }
5909
5910     /* actual comparing algorithm */
5911 //    size = AOP_SIZE( right );
5912
5913     falselbl = newiTempLabel( NULL );
5914     if(AOP_TYPE(left) == AOP_LIT) {
5915       /* compare to literal */
5916       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5917       
5918       if(sign) {
5919         pCodeOp *pct, *pct2;
5920         symbol *tlbl1;
5921
5922         /* signed compare */
5923         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5924
5925         pct = pic16_popCopyReg(&pic16_pc_prodl);
5926         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5927         tlbl = newiTempLabel( NULL );
5928         
5929         /* first compare signs:
5930          *  a. if both are positive, compare just like unsigned
5931          *  b. if both are negative, invert cmpop, compare just like unsigned
5932          *  c. if different signs, determine the result directly */
5933
5934         size--;
5935
5936 #if 1
5937         /* { */
5938         tlbl1 = newiTempLabel( NULL );
5939 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
5940
5941         if(lit > 0) {
5942
5943           /* literal is zero or positive:
5944            *  a. if carry is zero, too, continue compare,
5945            *  b. if carry is set, then continue depending on cmpop ^ condition:
5946            *    1. '<' return false (literal < variable),
5947            *    2. '>' return true (literal > variable) */
5948 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
5949           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5950           
5951           
5952           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5953           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
5954         } else 
5955         if(lit < 0) {
5956           
5957           /* literal is negative:
5958            *  a. if carry is set, too, continue compare,
5959            *  b. if carry is zero, then continue depending on cmpop ^ condition:
5960            *    1. '<' return true (literal < variable),
5961            *    2. '>' return false (literal > variable) */
5962 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
5963           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5964           
5965           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5966           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5967         }
5968 #if 1
5969         else {
5970           /* lit == 0 */
5971           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5972           
5973           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5974           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5975         }
5976 #endif
5977         
5978         
5979         pic16_emitpLabel( tlbl1->key );
5980 #endif  /* } */
5981
5982         compareAopfirstpass=1;
5983 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5984 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5985 //        pic16_emitpcode(POC_MOVWF, pct);
5986
5987 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5988         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5989 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5990         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5991
5992         /* generic case */        
5993           while( size-- ) {
5994 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5995 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
5996 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5997 //            pic16_emitpcode(POC_MOVWF, pct);
5998
5999 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6000             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6001             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6002 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6003 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6004           }
6005 //        }
6006         
6007         if(ifx)ifx->generated = 1;
6008
6009         if(AOP_SIZE(result)) {
6010           pic16_emitpLabel(tlbl->key);
6011           pic16_emitpLabel(falselbl->key);
6012           pic16_outBitOp( result, pct2 );
6013         } else {
6014           pic16_emitpLabel(tlbl->key);
6015         }
6016       } else {
6017
6018
6019         /* unsigned compare */      
6020         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6021     
6022         compareAopfirstpass=1;
6023         while(size--) {
6024           
6025           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6026           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6027
6028         }
6029
6030         if(ifx)ifx->generated = 1;
6031
6032
6033         if(AOP_SIZE(result)) {
6034           pic16_emitpLabel(falselbl->key);
6035           pic16_outBitC( result );
6036         }
6037
6038       }
6039     } else {
6040       /* compare registers */
6041       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6042
6043
6044       if(sign) {
6045         pCodeOp *pct, *pct2;
6046         
6047         /* signed compare */
6048         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6049
6050         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6051         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6052         tlbl = newiTempLabel( NULL );
6053         
6054         compareAopfirstpass=1;
6055
6056         size--;
6057         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6058 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6059         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6060         pic16_emitpcode(POC_MOVWF, pct);
6061
6062         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6063 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6064         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6065
6066         /* WREG already holds left + 0x80 */
6067         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6068         
6069         while( size-- ) {
6070           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6071 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6072           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6073           pic16_emitpcode(POC_MOVWF, pct);
6074                 
6075           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6076 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6077           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6078
6079           /* WREG already holds left + 0x80 */
6080           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6081 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6082         }
6083         
6084         if(ifx)ifx->generated = 1;
6085
6086         if(AOP_SIZE(result)) {
6087           pic16_emitpLabel(tlbl->key);
6088           pic16_emitpLabel(falselbl->key);
6089           pic16_outBitOp( result, pct2 );
6090         } else {
6091           pic16_emitpLabel(tlbl->key);
6092         }
6093
6094       } else {
6095         /* unsigned compare */      
6096         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6097
6098         compareAopfirstpass=1;
6099         while(size--) {
6100           
6101           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6102           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6103
6104         }
6105
6106         if(ifx)ifx->generated = 1;
6107         if(AOP_SIZE(result)) {
6108
6109           pic16_emitpLabel(falselbl->key);
6110           pic16_outBitC( result );
6111         }
6112
6113       }
6114     }
6115 }
6116
6117 #else    /* } else { */
6118
6119 /* new version of genCmp -- VR 20041012 */
6120 static void genCmp (operand *left,operand *right,
6121                     operand *result, iCode *ifx, int sign)
6122 {
6123   int size; //, offset = 0 ;
6124   unsigned long lit = 0L,i = 0;
6125   resolvedIfx rFalseIfx;
6126   int willCheckCarry=0;
6127   //  resolvedIfx rTrueIfx;
6128   symbol *truelbl;
6129
6130     FENTRY;
6131   
6132   /* General concept:
6133    * subtract right from left if at the end the carry flag is set then we
6134    * know that left is greater than right */
6135             
6136   resolveIfx(&rFalseIfx,ifx);
6137   truelbl  = newiTempLabel(NULL);
6138   size = max(AOP_SIZE(left),AOP_SIZE(right));
6139
6140   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6141
6142   /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
6143    * POC_CPFSLT compare f, wreg, skip if f less then wreg */
6144   
6145
6146   /* if literal is on the right then swap with left */
6147   if ((AOP_TYPE(right) == AOP_LIT)) {
6148     operand *tmp = right ;
6149     unsigned long mask = (0x100 << (8*(size-1))) - 1;
6150
6151       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6152
6153 //      lit = (lit - 1) & mask;
6154       right = left;
6155       left = tmp;
6156       rFalseIfx.condition ^= 1;         /* reverse compare */
6157   } else
6158   if ((AOP_TYPE(left) == AOP_LIT)) {
6159     /* float compares are handled by support functions */
6160     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
6161   }
6162
6163
6164   //if(IC_TRUE(ifx) == NULL)
6165   /* if left & right are bit variables */
6166   if (AOP_TYPE(left) == AOP_CRY &&
6167       AOP_TYPE(right) == AOP_CRY ) {
6168
6169     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6170     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6171
6172   } else {
6173     symbol *lbl  = newiTempLabel(NULL);
6174
6175     if(AOP_TYPE(left) == AOP_LIT) {
6176       DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
6177
6178       if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6179         willCheckCarry = 1;
6180       else willCheckCarry = 0;
6181
6182       /* Special cases */
6183       if((lit == 0) && (sign == 0)) {
6184         /* unsigned compare to 0 */
6185         DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
6186         
6187         size--;
6188         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6189         while(size) 
6190           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
6191
6192         genSkipz2(&rFalseIfx,0);
6193         if(ifx)ifx->generated = 1;
6194         return;
6195       }
6196
6197       if(size==1) {
6198         /* Special cases */
6199         lit &= 0xff;
6200         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
6201           /* degenerate compare can never be true */
6202           if(rFalseIfx.condition == 0)
6203             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
6204
6205           if(ifx) ifx->generated = 1;
6206           return;
6207         }
6208
6209         if(sign) {
6210           /* signed comparisons to a literal byte */
6211           DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6212
6213           int lp1 = (lit+1) & 0xff;
6214
6215           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
6216           switch (lp1) {
6217           case 0:
6218             rFalseIfx.condition ^= 1;
6219             genSkipCond(&rFalseIfx,right,0,7);
6220             break;
6221           case 0x7f:
6222             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6223             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
6224             genSkipz2(&rFalseIfx,1);
6225             break;
6226           default:
6227             pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
6228             
6229             if(rFalseIfx.condition)
6230               pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
6231             else
6232               pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
6233
6234             if(willCheckCarry) {
6235               if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
6236               else { emitSETC; emitCLRC; }
6237               
6238             } else {
6239               pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6240             }              
6241                       
6242 /*          pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6243             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6244             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
6245             rFalseIfx.condition ^= 1;
6246             genSkipc(&rFalseIfx);
6247 */
6248             break;
6249           }
6250         } else {
6251           /* unsigned comparisons to a literal byte */
6252           DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6253
6254           switch(lit & 0xff ) {
6255                           /* special cases */
6256           case 0:
6257             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6258             genSkipz2(&rFalseIfx,0);
6259             break;
6260           case 0x7f:
6261             rFalseIfx.condition ^= 1;
6262             genSkipCond(&rFalseIfx,right,0,7);
6263             break;
6264           default:
6265             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
6266             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6267             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6268             rFalseIfx.condition ^= 1;
6269             if (AOP_TYPE(result) == AOP_CRY)
6270               genSkipc(&rFalseIfx);
6271             else {
6272               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6273               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6274             }         
6275             break;
6276           }
6277         }
6278
6279         if(ifx) ifx->generated = 1;
6280         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6281                 goto check_carry;
6282         return;
6283
6284       } else {
6285
6286         /* Size is greater than 1 */
6287
6288         if(sign) {
6289           int lp1 = lit+1;
6290
6291           size--;
6292
6293           if(lp1 == 0) {
6294             /* this means lit = 0xffffffff, or -1 */
6295
6296
6297             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
6298             rFalseIfx.condition ^= 1;
6299             genSkipCond(&rFalseIfx,right,size,7);
6300             if(ifx) ifx->generated = 1;
6301             return;
6302           }
6303
6304           if(lit == 0) {
6305             int s = size;
6306
6307             if(rFalseIfx.condition) {
6308               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6309               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6310             }
6311
6312             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6313             while(size--)
6314               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6315
6316
6317             emitSKPZ;
6318             if(rFalseIfx.condition) {
6319               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6320               pic16_emitpLabel(truelbl->key);
6321             }else {
6322               rFalseIfx.condition ^= 1;
6323               genSkipCond(&rFalseIfx,right,s,7);
6324             }
6325
6326             if(ifx) ifx->generated = 1;
6327             return;
6328           }
6329
6330           if((size == 1) &&  (0 == (lp1&0xff))) {
6331             /* lower byte of signed word is zero */
6332             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
6333             i = ((lp1 >> 8) & 0xff) ^0x80;
6334             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6335             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6336             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6337             rFalseIfx.condition ^= 1;
6338             genSkipc(&rFalseIfx);
6339
6340
6341             if(ifx) ifx->generated = 1;
6342             return;
6343           }
6344
6345           if(lit & (0x80 << (size*8))) {
6346             /* Lit is less than zero */
6347             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
6348             //rFalseIfx.condition ^= 1;
6349             //genSkipCond(&rFalseIfx,left,size,7);
6350             //rFalseIfx.condition ^= 1;
6351             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6352             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6353
6354             if(rFalseIfx.condition)
6355               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6356             else
6357               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6358
6359
6360           } else {
6361             /* Lit is greater than or equal to zero */
6362             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
6363             //rFalseIfx.condition ^= 1;
6364             //genSkipCond(&rFalseIfx,right,size,7);
6365             //rFalseIfx.condition ^= 1;
6366
6367             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6368             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6369
6370             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6371             if(rFalseIfx.condition)
6372               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6373             else
6374               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6375
6376           }
6377
6378
6379           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6380           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6381
6382           while(size--) {
6383
6384             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6385             emitSKPNZ;
6386             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6387           }
6388           rFalseIfx.condition ^= 1;
6389           //rFalseIfx.condition = 1;
6390           genSkipc(&rFalseIfx);
6391
6392           pic16_emitpLabel(truelbl->key);
6393
6394           if(ifx) ifx->generated = 1;
6395           return;
6396           // end of if (sign)
6397         } else {
6398
6399           /* compare word or long to an unsigned literal on the right.*/
6400
6401
6402           size--;
6403           if(lit < 0xff) {
6404             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6405             switch (lit) {
6406             case 0:
6407               break; /* handled above */
6408 /*
6409             case 0xff:
6410               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6411               while(size--)
6412                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6413               genSkipz2(&rFalseIfx,0);
6414               break;
6415 */
6416             default:
6417               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6418               while(--size)
6419                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6420
6421               emitSKPZ;
6422               if(rFalseIfx.condition)
6423                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6424               else
6425                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6426
6427
6428               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6429               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6430
6431               rFalseIfx.condition ^= 1;
6432               genSkipc(&rFalseIfx);
6433             }
6434
6435             pic16_emitpLabel(truelbl->key);
6436
6437             if(ifx) ifx->generated = 1;
6438             return;
6439           }
6440
6441
6442           lit++;
6443           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6444           i = (lit >> (size*8)) & 0xff;
6445
6446           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6447           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6448
6449           while(size--) {
6450             i = (lit >> (size*8)) & 0xff;
6451
6452             if(i) {
6453               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6454               emitSKPNZ;
6455               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6456             } else {
6457               /* this byte of the lit is zero, 
6458                * if it's not the last then OR in the variable */
6459               if(size)
6460                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6461             }
6462           }
6463
6464
6465           pic16_emitpLabel(lbl->key);
6466
6467           rFalseIfx.condition ^= 1;
6468
6469           genSkipc(&rFalseIfx);
6470         }
6471
6472         if(sign)
6473           pic16_emitpLabel(truelbl->key);
6474         if(ifx) ifx->generated = 1;
6475         return;
6476       }
6477     }
6478     /* Compare two variables */
6479
6480     DEBUGpic16_emitcode(";sign","%d",sign);
6481
6482     size--;
6483     if(sign) {
6484       /* Sigh. thus sucks... */
6485       if(size) {
6486         pCodeOp *pctemp;
6487         
6488         pctemp = pic16_popGetTempReg(1);
6489         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6490         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6491         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6492         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6493         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6494         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6495         pic16_popReleaseTempReg(pctemp, 1);
6496       } else {
6497         /* Signed char comparison */
6498         /* Special thanks to Nikolai Golovchenko for this snippet */
6499         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6500         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6501         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
6502         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6503         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6504         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6505
6506         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6507         genSkipc(&rFalseIfx);
6508           
6509         if(ifx) ifx->generated = 1;
6510         return;
6511       }
6512
6513     } else {
6514
6515       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6516       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6517     }
6518
6519
6520     /* The rest of the bytes of a multi-byte compare */
6521     while (size) {
6522
6523       emitSKPZ;
6524       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
6525       size--;
6526
6527       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6528       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6529
6530
6531     }
6532
6533     pic16_emitpLabel(lbl->key);
6534
6535     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6536     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
6537         (AOP_TYPE(result) == AOP_REG)) {
6538       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6539       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6540     } else {
6541       genSkipc(&rFalseIfx);
6542     }         
6543     //genSkipc(&rFalseIfx);
6544     if(ifx) ifx->generated = 1;
6545
6546     return;
6547
6548   }
6549
6550 check_carry:
6551   if ((AOP_TYPE(result) != AOP_CRY) 
6552         && AOP_SIZE(result)) {
6553     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6554
6555     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6556
6557     pic16_outBitC(result);
6558   } else {
6559     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6560     /* if the result is used in the next
6561        ifx conditional branch then generate
6562        code a little differently */
6563     if (ifx )
6564       genIfxJump (ifx,"c");
6565     else
6566       pic16_outBitC(result);
6567     /* leave the result in acc */
6568   }
6569
6570 }
6571 #endif  /* } */
6572
6573
6574 #endif  /* } */
6575
6576
6577
6578 /*-----------------------------------------------------------------*/
6579 /* genCmpGt :- greater than comparison                             */
6580 /*-----------------------------------------------------------------*/
6581 static void genCmpGt (iCode *ic, iCode *ifx)
6582 {
6583   operand *left, *right, *result;
6584   sym_link *letype , *retype;
6585   int sign ;
6586
6587     FENTRY;
6588     
6589     left = IC_LEFT(ic);
6590     right= IC_RIGHT(ic);
6591     result = IC_RESULT(ic);
6592
6593     letype = getSpec(operandType(left));
6594     retype =getSpec(operandType(right));
6595     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6596     /* assign the amsops */
6597     pic16_aopOp (left,ic,FALSE);
6598     pic16_aopOp (right,ic,FALSE);
6599     pic16_aopOp (result,ic,TRUE);
6600
6601     genCmp(right, left, result, ifx, sign);
6602
6603     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6604     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6605     pic16_freeAsmop(result,NULL,ic,TRUE); 
6606 }
6607
6608 /*-----------------------------------------------------------------*/
6609 /* genCmpLt - less than comparisons                                */
6610 /*-----------------------------------------------------------------*/
6611 static void genCmpLt (iCode *ic, iCode *ifx)
6612 {
6613   operand *left, *right, *result;
6614   sym_link *letype , *retype;
6615   int sign ;
6616
6617     FENTRY;
6618
6619     left = IC_LEFT(ic);
6620     right= IC_RIGHT(ic);
6621     result = IC_RESULT(ic);
6622
6623     letype = getSpec(operandType(left));
6624     retype =getSpec(operandType(right));
6625     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6626
6627     /* assign the amsops */
6628     pic16_aopOp (left,ic,FALSE);
6629     pic16_aopOp (right,ic,FALSE);
6630     pic16_aopOp (result,ic,TRUE);
6631
6632     genCmp(left, right, result, ifx, sign);
6633
6634     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6635     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6636     pic16_freeAsmop(result,NULL,ic,TRUE); 
6637 }
6638
6639 #if 0
6640 // not needed ATM
6641 // FIXME reenable literal optimisation when the pic16 port is stable
6642
6643 /*-----------------------------------------------------------------*/
6644 /* genc16bit2lit - compare a 16 bit value to a literal             */
6645 /*-----------------------------------------------------------------*/
6646 static void genc16bit2lit(operand *op, int lit, int offset)
6647 {
6648   int i;
6649
6650   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6651   if( (lit&0xff) == 0) 
6652     i=1;
6653   else
6654     i=0;
6655
6656   switch( BYTEofLONG(lit,i)) { 
6657   case 0:
6658     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6659     break;
6660   case 1:
6661     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6662     break;
6663   case 0xff:
6664     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6665     break;
6666   default:
6667     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6668     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6669   }
6670
6671   i ^= 1;
6672
6673   switch( BYTEofLONG(lit,i)) { 
6674   case 0:
6675     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6676     break;
6677   case 1:
6678     emitSKPNZ;
6679     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6680     break;
6681   case 0xff:
6682     emitSKPNZ;
6683     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6684     break;
6685   default:
6686     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6687     emitSKPNZ;
6688     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6689
6690   }
6691
6692 }
6693 #endif
6694
6695 #if 0
6696 // not needed ATM
6697 /*-----------------------------------------------------------------*/
6698 /* gencjneshort - compare and jump if not equal                    */
6699 /*-----------------------------------------------------------------*/
6700 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6701 {
6702   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6703   int offset = 0;
6704   int res_offset = 0;  /* the result may be a different size then left or right */
6705   int res_size = AOP_SIZE(result);
6706   resolvedIfx rIfx;
6707   symbol *lbl, *lbl_done;
6708
6709   unsigned long lit = 0L;
6710   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6711
6712   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6713   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6714   if(result)
6715     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6716   resolveIfx(&rIfx,ifx);
6717   lbl =  newiTempLabel(NULL);
6718   lbl_done =  newiTempLabel(NULL);
6719
6720
6721   /* if the left side is a literal or 
6722      if the right is in a pointer register and left 
6723      is not */
6724   if ((AOP_TYPE(left) == AOP_LIT) || 
6725       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6726     operand *t = right;
6727     right = left;
6728     left = t;
6729   }
6730   if(AOP_TYPE(right) == AOP_LIT)
6731     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6732
6733   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6734     preserve_result = 1;
6735
6736   if(result && !preserve_result)
6737     {
6738       int i;
6739       for(i = 0; i < AOP_SIZE(result); i++)
6740         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6741     }
6742
6743
6744   /* if the right side is a literal then anything goes */
6745   if (AOP_TYPE(right) == AOP_LIT &&
6746       AOP_TYPE(left) != AOP_DIR ) {
6747     switch(size) {
6748     case 2:
6749       genc16bit2lit(left, lit, 0);
6750       emitSKPZ;
6751       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6752       break;
6753     default:
6754       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6755       while (size--) {
6756         if(lit & 0xff) {
6757           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6758           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6759         } else {
6760           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6761         }
6762
6763         emitSKPZ;
6764         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6765         offset++;
6766         if(res_offset < res_size-1)
6767           res_offset++;
6768         lit >>= 8;
6769       }
6770       break;
6771     }
6772   }
6773
6774   /* if the right side is in a register or in direct space or
6775      if the left is a pointer register & right is not */    
6776   else if (AOP_TYPE(right) == AOP_REG ||
6777            AOP_TYPE(right) == AOP_DIR || 
6778            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6779            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6780     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6781     int lbl_key = lbl->key;
6782
6783     if(result) {
6784       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6785       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6786     }else {
6787       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6788       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6789               __FUNCTION__,__LINE__);
6790       return;
6791     }
6792    
6793 /*     switch(size) { */
6794 /*     case 2: */
6795 /*       genc16bit2lit(left, lit, 0); */
6796 /*       emitSKPNZ; */
6797 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6798 /*       break; */
6799 /*     default: */
6800     while (size--) {
6801       int emit_skip=1;
6802       if((AOP_TYPE(left) == AOP_DIR) && 
6803          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6804
6805         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6806         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6807
6808       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6809             
6810         switch (lit & 0xff) {
6811         case 0:
6812           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6813           break;
6814         case 1:
6815           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6816           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6817           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6818           emit_skip=0;
6819           break;
6820         case 0xff:
6821           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6822           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6823           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6824           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6825           emit_skip=0;
6826           break;
6827         default:
6828           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6829           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6830         }
6831         lit >>= 8;
6832
6833       } else {
6834         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6835       }
6836       if(emit_skip) {
6837         if(AOP_TYPE(result) == AOP_CRY) {
6838           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6839           if(rIfx.condition)
6840             emitSKPNZ;
6841           else
6842             emitSKPZ;
6843           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6844         } else {
6845           /* fix me. probably need to check result size too */
6846           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6847           if(rIfx.condition)
6848             emitSKPZ;
6849           else
6850             emitSKPNZ;
6851           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6852           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6853         }
6854         if(ifx)
6855           ifx->generated=1;
6856       }
6857       emit_skip++;
6858       offset++;
6859       if(res_offset < res_size-1)
6860         res_offset++;
6861     }
6862 /*       break; */
6863 /*     } */
6864   } else if(AOP_TYPE(right) == AOP_REG &&
6865             AOP_TYPE(left) != AOP_DIR){
6866
6867     while(size--) {
6868       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6869       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6870       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6871       if(rIfx.condition)
6872         emitSKPNZ;
6873       else
6874         emitSKPZ;
6875       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6876       offset++;
6877       if(res_offset < res_size-1)
6878         res_offset++;
6879     }
6880       
6881   }else{
6882     /* right is a pointer reg need both a & b */
6883     while(size--) {
6884       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6885       if(strcmp(l,"b"))
6886         pic16_emitcode("mov","b,%s",l);
6887       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6888       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6889       offset++;
6890     }
6891   }
6892
6893   if(result && preserve_result)
6894     {
6895       int i;
6896       for(i = 0; i < AOP_SIZE(result); i++)
6897         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6898     }
6899
6900   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6901
6902   if(result && preserve_result)
6903     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6904
6905   if(!rIfx.condition)
6906     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6907
6908   pic16_emitpLabel(lbl->key);
6909
6910   if(result && preserve_result)
6911     {
6912       int i;
6913       for(i = 0; i < AOP_SIZE(result); i++)
6914         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6915
6916       pic16_emitpLabel(lbl_done->key);
6917    }
6918
6919   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6920
6921   if(ifx)
6922     ifx->generated = 1;
6923 }
6924 #endif
6925
6926 #if 0
6927 /*-----------------------------------------------------------------*/
6928 /* gencjne - compare and jump if not equal                         */
6929 /*-----------------------------------------------------------------*/
6930 static void gencjne(operand *left, operand *right, iCode *ifx)
6931 {
6932     symbol *tlbl  = newiTempLabel(NULL);
6933
6934     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6935     gencjneshort(left, right, lbl);
6936
6937     pic16_emitcode("mov","a,%s",one);
6938     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6939     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6940     pic16_emitcode("clr","a");
6941     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6942
6943     pic16_emitpLabel(lbl->key);
6944     pic16_emitpLabel(tlbl->key);
6945
6946 }
6947 #endif
6948
6949
6950 /*-----------------------------------------------------------------*/
6951 /* is_LitOp - check if operand has to be treated as literal        */
6952 /*-----------------------------------------------------------------*/
6953 static bool is_LitOp(operand *op)
6954 {
6955   return ((AOP_TYPE(op) == AOP_LIT)
6956       || ( (AOP_TYPE(op) == AOP_PCODE)
6957           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6958               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6959 }
6960
6961 /*-----------------------------------------------------------------*/
6962 /* is_LitAOp - check if operand has to be treated as literal        */
6963 /*-----------------------------------------------------------------*/
6964 static bool is_LitAOp(asmop *aop)
6965 {
6966   return ((aop->type == AOP_LIT)
6967       || ( (aop->type == AOP_PCODE)
6968           && ( (aop->aopu.pcop->type == PO_LITERAL)
6969               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6970 }
6971
6972
6973
6974 /*-----------------------------------------------------------------*/
6975 /* genCmpEq - generates code for equal to                          */
6976 /*-----------------------------------------------------------------*/
6977 static void genCmpEq (iCode *ic, iCode *ifx)
6978 {
6979   operand *left, *right, *result;
6980   symbol *falselbl = newiTempLabel(NULL);
6981   symbol *donelbl = newiTempLabel(NULL);
6982
6983   int preserve_result = 0;
6984   int generate_result = 0;
6985   int i=0;
6986
6987   FENTRY;
6988   
6989   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6990   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6991   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6992  
6993   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6994
6995   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6996     {
6997       werror(W_POSSBUG2, __FILE__, __LINE__);
6998       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6999       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
7000       goto release;
7001     }
7002
7003   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
7004     {
7005       operand *tmp = right ;
7006       right = left;
7007       left = tmp;
7008     }
7009
7010   if ( regsInCommon(left, result) || regsInCommon(right, result) )
7011     preserve_result = 1;
7012
7013   if(result && AOP_SIZE(result))
7014     generate_result = 1;
7015
7016   if(generate_result && !preserve_result)
7017     {
7018       for(i = 0; i < AOP_SIZE(result); i++)
7019         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7020     }
7021
7022   for(i=0; i < AOP_SIZE(left); i++)
7023     {
7024       if(AOP_TYPE(left) != AOP_ACC)
7025         {
7026           if(is_LitOp(left))
7027             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
7028           else
7029             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
7030         }
7031       if(is_LitOp(right))
7032         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
7033       else
7034         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
7035
7036       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
7037     }
7038
7039   // result == true
7040
7041   if(generate_result && preserve_result)
7042     {
7043       for(i = 0; i < AOP_SIZE(result); i++)
7044         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7045     }
7046
7047   if(generate_result)
7048     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7049
7050   if(generate_result && preserve_result)
7051     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7052
7053   if(ifx && IC_TRUE(ifx))
7054     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7055
7056   if(ifx && IC_FALSE(ifx))
7057     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7058
7059   pic16_emitpLabel(falselbl->key);
7060
7061   // result == false
7062
7063   if(ifx && IC_FALSE(ifx))
7064     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7065
7066   if(generate_result && preserve_result)
7067     {
7068       for(i = 0; i < AOP_SIZE(result); i++)
7069         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7070     }
7071
7072   pic16_emitpLabel(donelbl->key);
7073
7074   if(ifx)
7075     ifx->generated = 1;
7076
7077 release:
7078   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7079   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7080   pic16_freeAsmop(result,NULL,ic,TRUE);
7081
7082 }
7083
7084
7085 #if 0
7086 // old version kept for reference
7087
7088 /*-----------------------------------------------------------------*/
7089 /* genCmpEq - generates code for equal to                          */
7090 /*-----------------------------------------------------------------*/
7091 static void genCmpEq (iCode *ic, iCode *ifx)
7092 {
7093     operand *left, *right, *result;
7094     unsigned long lit = 0L;
7095     int size,offset=0;
7096     symbol *falselbl  = newiTempLabel(NULL);
7097
7098
7099     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7100
7101     if(ifx)
7102       DEBUGpic16_emitcode ("; ifx is non-null","");
7103     else
7104       DEBUGpic16_emitcode ("; ifx is null","");
7105
7106     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7107     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7108     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7109
7110     size = max(AOP_SIZE(left),AOP_SIZE(right));
7111
7112     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7113
7114     /* if literal, literal on the right or 
7115     if the right is in a pointer register and left 
7116     is not */
7117     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
7118         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7119       operand *tmp = right ;
7120       right = left;
7121       left = tmp;
7122     }
7123
7124
7125     if(ifx && !AOP_SIZE(result)){
7126         symbol *tlbl;
7127         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
7128         /* if they are both bit variables */
7129         if (AOP_TYPE(left) == AOP_CRY &&
7130             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7131                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
7132             if(AOP_TYPE(right) == AOP_LIT){
7133                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7134                 if(lit == 0L){
7135                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7136                     pic16_emitcode("cpl","c");
7137                 } else if(lit == 1L) {
7138                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7139                 } else {
7140                     pic16_emitcode("clr","c");
7141                 }
7142                 /* AOP_TYPE(right) == AOP_CRY */
7143             } else {
7144                 symbol *lbl = newiTempLabel(NULL);
7145                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7146                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7147                 pic16_emitcode("cpl","c");
7148                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7149             }
7150             /* if true label then we jump if condition
7151             supplied is true */
7152             tlbl = newiTempLabel(NULL);
7153             if ( IC_TRUE(ifx) ) {
7154                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7155                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7156             } else {
7157                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7158                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7159             }
7160             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7161
7162                 {
7163                 /* left and right are both bit variables, result is carry */
7164                         resolvedIfx rIfx;
7165               
7166                         resolveIfx(&rIfx,ifx);
7167
7168                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7169                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7170                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7171                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7172                         genSkipz2(&rIfx,0);
7173                 }
7174         } else {
7175
7176                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
7177
7178                         /* They're not both bit variables. Is the right a literal? */
7179                         if(AOP_TYPE(right) == AOP_LIT) {
7180                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7181             
7182                         switch(size) {
7183
7184                                 case 1:
7185                                         switch(lit & 0xff) {
7186                                                 case 1:
7187                                                                 if ( IC_TRUE(ifx) ) {
7188                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7189                                                                         emitSKPNZ;
7190                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7191                                                                 } else {
7192                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7193                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7194                                                                 }
7195                                                                 break;
7196                                                 case 0xff:
7197                                                                 if ( IC_TRUE(ifx) ) {
7198                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7199                                                                         emitSKPNZ;
7200                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7201                                                                 } else {
7202                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7203                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7204                                                                 }
7205                                                                 break;
7206                                                 default:
7207                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7208                                                                 if(lit)
7209                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7210                                                                 genSkip(ifx,'z');
7211                                         } // switch lit
7212
7213
7214                                         /* end of size == 1 */
7215                                         break;
7216               
7217                                 case 2:
7218                                         genc16bit2lit(left,lit,offset);
7219                                         genSkip(ifx,'z');
7220                                         break;
7221                                         /* end of size == 2 */
7222
7223                                 default:
7224                                         /* size is 4 */
7225                                         if(lit==0) {
7226                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7227                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7228                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7229                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7230                                                 genSkip(ifx,'z');
7231                                         } else {
7232                                                 /* search for patterns that can be optimized */
7233
7234                                                 genc16bit2lit(left,lit,0);
7235                                                 lit >>= 16;
7236                                                 if(lit) {
7237                                                                 if(IC_TRUE(ifx))
7238                                                                 emitSKPZ; // if hi word unequal
7239                                                                 else
7240                                                                 emitSKPNZ; // if hi word equal
7241                                                                 // fail early
7242                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7243                                                         genc16bit2lit(left,lit,2);
7244                                                         genSkip(ifx,'z');
7245                                                 } else {
7246                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7247                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7248                                                         genSkip(ifx,'z');
7249                                                 }
7250                                         }
7251                                                 pic16_emitpLabel(falselbl->key);
7252                                                 break;
7253
7254                         } // switch size
7255           
7256                         ifx->generated = 1;
7257                         goto release ;
7258             
7259
7260           } else if(AOP_TYPE(right) == AOP_CRY ) {
7261             /* we know the left is not a bit, but that the right is */
7262             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7263             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7264                       pic16_popGet(AOP(right),offset));
7265             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7266
7267             /* if the two are equal, then W will be 0 and the Z bit is set
7268              * we could test Z now, or go ahead and check the high order bytes if
7269              * the variable we're comparing is larger than a byte. */
7270
7271             while(--size)
7272               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7273
7274             if ( IC_TRUE(ifx) ) {
7275               emitSKPNZ;
7276               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7277               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7278             } else {
7279               emitSKPZ;
7280               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7281               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7282             }
7283
7284           } else {
7285             /* They're both variables that are larger than bits */
7286             int s = size;
7287
7288             tlbl = newiTempLabel(NULL);
7289
7290             while(size--) {
7291               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7292               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7293
7294               if ( IC_TRUE(ifx) ) {
7295                 if(size) {
7296                   emitSKPZ;
7297                 
7298                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7299
7300                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7301                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7302                 } else {
7303                   emitSKPNZ;
7304
7305                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7306
7307
7308                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7309                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7310                 }
7311               } else {
7312                 emitSKPZ;
7313
7314                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7315
7316                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7317                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7318               }
7319               offset++;
7320             }
7321             if(s>1 && IC_TRUE(ifx)) {
7322               pic16_emitpLabel(tlbl->key);
7323               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7324             }
7325           }
7326         }
7327         /* mark the icode as generated */
7328         ifx->generated = 1;
7329         goto release ;
7330     }
7331
7332     /* if they are both bit variables */
7333     if (AOP_TYPE(left) == AOP_CRY &&
7334         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7335         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7336         if(AOP_TYPE(right) == AOP_LIT){
7337             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7338             if(lit == 0L){
7339                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7340                 pic16_emitcode("cpl","c");
7341             } else if(lit == 1L) {
7342                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7343             } else {
7344                 pic16_emitcode("clr","c");
7345             }
7346             /* AOP_TYPE(right) == AOP_CRY */
7347         } else {
7348             symbol *lbl = newiTempLabel(NULL);
7349             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7350             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7351             pic16_emitcode("cpl","c");
7352             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7353         }
7354         /* c = 1 if egal */
7355         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7356             pic16_outBitC(result);
7357             goto release ;
7358         }
7359         if (ifx) {
7360             genIfxJump (ifx,"c");
7361             goto release ;
7362         }
7363         /* if the result is used in an arithmetic operation
7364         then put the result in place */
7365         pic16_outBitC(result);
7366     } else {
7367       
7368       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7369       gencjne(left,right,result,ifx);
7370 /*
7371       if(ifx) 
7372         gencjne(left,right,newiTempLabel(NULL));
7373       else {
7374         if(IC_TRUE(ifx)->key)
7375           gencjne(left,right,IC_TRUE(ifx)->key);
7376         else
7377           gencjne(left,right,IC_FALSE(ifx)->key);
7378         ifx->generated = 1;
7379         goto release ;
7380       }
7381       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7382         pic16_aopPut(AOP(result),"a",0);
7383         goto release ;
7384       }
7385
7386       if (ifx) {
7387         genIfxJump (ifx,"a");
7388         goto release ;
7389       }
7390 */
7391       /* if the result is used in an arithmetic operation
7392          then put the result in place */
7393 /*
7394       if (AOP_TYPE(result) != AOP_CRY) 
7395         pic16_outAcc(result);
7396 */
7397       /* leave the result in acc */
7398     }
7399
7400 release:
7401     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7402     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7403     pic16_freeAsmop(result,NULL,ic,TRUE);
7404 }
7405 #endif
7406
7407 /*-----------------------------------------------------------------*/
7408 /* ifxForOp - returns the icode containing the ifx for operand     */
7409 /*-----------------------------------------------------------------*/
7410 static iCode *ifxForOp ( operand *op, iCode *ic )
7411 {
7412   FENTRY2;
7413
7414     /* if true symbol then needs to be assigned */
7415     if (IS_TRUE_SYMOP(op))
7416         return NULL ;
7417
7418     /* if this has register type condition and
7419     the next instruction is ifx with the same operand
7420     and live to of the operand is upto the ifx only then */
7421     if (ic->next
7422         && ic->next->op == IFX
7423         && IC_COND(ic->next)->key == op->key
7424         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7425         ) {
7426                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7427           return ic->next;
7428     }
7429
7430     /*
7431     if (ic->next &&
7432         ic->next->op == IFX &&
7433         IC_COND(ic->next)->key == op->key) {
7434       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7435       return ic->next;
7436     }
7437     */
7438
7439     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7440     if (ic->next &&
7441         ic->next->op == IFX)
7442       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7443
7444     if (ic->next &&
7445         ic->next->op == IFX &&
7446         IC_COND(ic->next)->key == op->key) {
7447       DEBUGpic16_emitcode ("; "," key is okay");
7448       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7449                            OP_SYMBOL(op)->liveTo,
7450                            ic->next->seq);
7451     }
7452
7453 #if 0
7454     /* the code below is completely untested
7455      * it just allows ulong2fs.c compile -- VR */
7456          
7457     ic = ic->next;
7458     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7459                                         __FILE__, __FUNCTION__, __LINE__);
7460         
7461     /* if this has register type condition and
7462     the next instruction is ifx with the same operand
7463     and live to of the operand is upto the ifx only then */
7464     if (ic->next &&
7465         ic->next->op == IFX &&
7466         IC_COND(ic->next)->key == op->key &&
7467         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7468         return ic->next;
7469
7470     if (ic->next &&
7471         ic->next->op == IFX &&
7472         IC_COND(ic->next)->key == op->key) {
7473       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7474       return ic->next;
7475     }
7476
7477     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7478                                         __FILE__, __FUNCTION__, __LINE__);
7479
7480 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7481 #endif
7482
7483     return NULL;
7484 }
7485 /*-----------------------------------------------------------------*/
7486 /* genAndOp - for && operation                                     */
7487 /*-----------------------------------------------------------------*/
7488 static void genAndOp (iCode *ic)
7489 {
7490   operand *left,*right, *result;
7491 /*     symbol *tlbl; */
7492
7493     FENTRY;
7494
7495     /* note here that && operations that are in an
7496     if statement are taken away by backPatchLabels
7497     only those used in arthmetic operations remain */
7498     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7499     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7500     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7501
7502     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7503
7504     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7505     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7506     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7507
7508     /* if both are bit variables */
7509 /*     if (AOP_TYPE(left) == AOP_CRY && */
7510 /*         AOP_TYPE(right) == AOP_CRY ) { */
7511 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7512 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7513 /*         pic16_outBitC(result); */
7514 /*     } else { */
7515 /*         tlbl = newiTempLabel(NULL); */
7516 /*         pic16_toBoolean(left);     */
7517 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7518 /*         pic16_toBoolean(right); */
7519 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7520 /*         pic16_outBitAcc(result); */
7521 /*     } */
7522
7523     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7524     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7525     pic16_freeAsmop(result,NULL,ic,TRUE);
7526 }
7527
7528
7529 /*-----------------------------------------------------------------*/
7530 /* genOrOp - for || operation                                      */
7531 /*-----------------------------------------------------------------*/
7532 /*
7533   tsd pic port -
7534   modified this code, but it doesn't appear to ever get called
7535 */
7536
7537 static void genOrOp (iCode *ic)
7538 {
7539   operand *left,*right, *result;
7540   symbol *tlbl;
7541
7542     FENTRY;  
7543
7544   /* note here that || operations that are in an
7545     if statement are taken away by backPatchLabels
7546     only those used in arthmetic operations remain */
7547     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7548     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7549     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7550
7551     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7552
7553     /* if both are bit variables */
7554     if (AOP_TYPE(left) == AOP_CRY &&
7555         AOP_TYPE(right) == AOP_CRY ) {
7556       pic16_emitcode("clrc","");
7557       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7558                AOP(left)->aopu.aop_dir,
7559                AOP(left)->aopu.aop_dir);
7560       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7561                AOP(right)->aopu.aop_dir,
7562                AOP(right)->aopu.aop_dir);
7563       pic16_emitcode("setc","");
7564
7565     } else {
7566         tlbl = newiTempLabel(NULL);
7567         pic16_toBoolean(left);
7568         emitSKPZ;
7569         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7570         pic16_toBoolean(right);
7571         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7572
7573         pic16_outBitAcc(result);
7574     }
7575
7576     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7577     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7578     pic16_freeAsmop(result,NULL,ic,TRUE);            
7579 }
7580
7581 /*-----------------------------------------------------------------*/
7582 /* isLiteralBit - test if lit == 2^n                               */
7583 /*-----------------------------------------------------------------*/
7584 static int isLiteralBit(unsigned long lit)
7585 {
7586     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7587     0x100L,0x200L,0x400L,0x800L,
7588     0x1000L,0x2000L,0x4000L,0x8000L,
7589     0x10000L,0x20000L,0x40000L,0x80000L,
7590     0x100000L,0x200000L,0x400000L,0x800000L,
7591     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7592     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7593     int idx;
7594     
7595     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7596     for(idx = 0; idx < 32; idx++)
7597         if(lit == pw[idx])
7598             return idx+1;
7599     return 0;
7600 }
7601
7602 /*-----------------------------------------------------------------*/
7603 /* continueIfTrue -                                                */
7604 /*-----------------------------------------------------------------*/
7605 static void continueIfTrue (iCode *ic)
7606 {
7607   FENTRY;
7608   if(IC_TRUE(ic))
7609     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7610   ic->generated = 1;
7611 }
7612
7613 /*-----------------------------------------------------------------*/
7614 /* jmpIfTrue -                                                     */
7615 /*-----------------------------------------------------------------*/
7616 static void jumpIfTrue (iCode *ic)
7617 {
7618   FENTRY;
7619   if(!IC_TRUE(ic))
7620     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7621   ic->generated = 1;
7622 }
7623
7624 /*-----------------------------------------------------------------*/
7625 /* jmpTrueOrFalse -                                                */
7626 /*-----------------------------------------------------------------*/
7627 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7628 {
7629   // ugly but optimized by peephole
7630   FENTRY;
7631   if(IC_TRUE(ic)){
7632     symbol *nlbl = newiTempLabel(NULL);
7633       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7634       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7635       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7636       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7637   } else {
7638     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7639     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7640   }
7641   ic->generated = 1;
7642 }
7643
7644 /*-----------------------------------------------------------------*/
7645 /* genAnd  - code for and                                          */
7646 /*-----------------------------------------------------------------*/
7647 static void genAnd (iCode *ic, iCode *ifx)
7648 {
7649   operand *left, *right, *result;
7650   int size, offset=0;  
7651   unsigned long lit = 0L;
7652   int bytelit = 0;
7653   resolvedIfx rIfx;
7654
7655     FENTRY;
7656     
7657   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7658   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7659   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7660
7661   resolveIfx(&rIfx,ifx);
7662
7663   /* if left is a literal & right is not then exchange them */
7664   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7665       AOP_NEEDSACC(left)) {
7666     operand *tmp = right ;
7667     right = left;
7668     left = tmp;
7669   }
7670
7671   /* if result = right then exchange them */
7672   if(pic16_sameRegs(AOP(result),AOP(right))){
7673     operand *tmp = right ;
7674     right = left;
7675     left = tmp;
7676   }
7677
7678   /* if right is bit then exchange them */
7679   if (AOP_TYPE(right) == AOP_CRY &&
7680       AOP_TYPE(left) != AOP_CRY){
7681     operand *tmp = right ;
7682     right = left;
7683     left = tmp;
7684   }
7685   if(AOP_TYPE(right) == AOP_LIT)
7686     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7687
7688   size = AOP_SIZE(result);
7689
7690   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7691
7692   // if(bit & yy)
7693   // result = bit & yy;
7694   if (AOP_TYPE(left) == AOP_CRY){
7695     // c = bit & literal;
7696     if(AOP_TYPE(right) == AOP_LIT){
7697       if(lit & 1) {
7698         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7699           // no change
7700           goto release;
7701         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7702       } else {
7703         // bit(result) = 0;
7704         if(size && (AOP_TYPE(result) == AOP_CRY)){
7705           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7706           goto release;
7707         }
7708         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7709           jumpIfTrue(ifx);
7710           goto release;
7711         }
7712         pic16_emitcode("clr","c");
7713       }
7714     } else {
7715       if (AOP_TYPE(right) == AOP_CRY){
7716         // c = bit & bit;
7717         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7718         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7719       } else {
7720         // c = bit & val;
7721         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7722         // c = lsb
7723         pic16_emitcode("rrc","a");
7724         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7725       }
7726     }
7727     // bit = c
7728     // val = c
7729     if(size)
7730       pic16_outBitC(result);
7731     // if(bit & ...)
7732     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7733       genIfxJump(ifx, "c");           
7734     goto release ;
7735   }
7736
7737   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7738   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7739   if((AOP_TYPE(right) == AOP_LIT) &&
7740      (AOP_TYPE(result) == AOP_CRY) &&
7741      (AOP_TYPE(left) != AOP_CRY)){
7742     int posbit = isLiteralBit(lit);
7743     /* left &  2^n */
7744     if(posbit){
7745       posbit--;
7746       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7747       // bit = left & 2^n
7748       if(size)
7749         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7750       // if(left &  2^n)
7751       else{
7752         if(ifx){
7753 /*
7754           if(IC_TRUE(ifx)) {
7755             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7756             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7757           } else {
7758             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7759             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7760           }
7761 */
7762         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7763         size = AOP_SIZE(left);
7764
7765         {
7766           int bp = posbit, ofs=0;
7767           
7768             while(bp > 7) {
7769               bp -= 8;
7770               ofs++;
7771             }
7772         
7773           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7774                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7775
7776         }
7777 /*
7778           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7779                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7780 */
7781           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7782           
7783           ifx->generated = 1;
7784         }
7785         goto release;
7786       }
7787     } else {
7788       symbol *tlbl = newiTempLabel(NULL);
7789       int sizel = AOP_SIZE(left);
7790
7791       if(size)
7792         emitSETC;
7793
7794       while(sizel--) {
7795         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7796
7797           /* patch provided by Aaron Colwell */
7798           if((posbit = isLiteralBit(bytelit)) != 0) {
7799               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7800                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7801                                                 (posbit-1),0, PO_GPR_REGISTER));
7802
7803               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7804 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7805           } else {
7806               if (bytelit == 0xff) {
7807                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7808                    * a peephole could optimize it out -- VR */
7809                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7810               } else {
7811                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7812                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7813               }
7814
7815               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7816                             pic16_popGetLabel(tlbl->key));
7817           }
7818         
7819 #if 0
7820           /* old code, left here for reference -- VR 09/2004 */
7821           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7822           // byte ==  2^n ?
7823           if((posbit = isLiteralBit(bytelit)) != 0)
7824             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7825           else{
7826             if(bytelit != 0x0FFL)
7827               pic16_emitcode("anl","a,%s",
7828                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7829             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7830           }
7831 #endif
7832         }
7833         offset++;
7834       }
7835       // bit = left & literal
7836       if(size) {
7837         emitCLRC;
7838         pic16_emitpLabel(tlbl->key);
7839       }
7840       // if(left & literal)
7841       else {
7842         if(ifx) {
7843           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7844           ifx->generated = 1;
7845         }
7846         pic16_emitpLabel(tlbl->key);
7847         goto release;
7848       }
7849     }
7850
7851     pic16_outBitC(result);
7852     goto release ;
7853   }
7854
7855   /* if left is same as result */
7856   if(pic16_sameRegs(AOP(result),AOP(left))){
7857     int know_W = -1;
7858     for(;size--; offset++,lit>>=8) {
7859       if(AOP_TYPE(right) == AOP_LIT){
7860         switch(lit & 0xff) {
7861         case 0x00:
7862           /*  and'ing with 0 has clears the result */
7863 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7864           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7865           break;
7866         case 0xff:
7867           /* and'ing with 0xff is a nop when the result and left are the same */
7868           break;
7869
7870         default:
7871           {
7872             int p = pic16_my_powof2( (~lit) & 0xff );
7873             if(p>=0) {
7874               /* only one bit is set in the literal, so use a bcf instruction */
7875 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7876               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7877
7878             } else {
7879               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7880               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7881               if(know_W != (lit&0xff))
7882                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7883               know_W = lit &0xff;
7884               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7885             }
7886           }    
7887         }
7888       } else {
7889         if (AOP_TYPE(left) == AOP_ACC) {
7890           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7891         } else {                    
7892           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7893           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7894
7895         }
7896       }
7897     }
7898
7899   } else {
7900     // left & result in different registers
7901     if(AOP_TYPE(result) == AOP_CRY){
7902       // result = bit
7903       // if(size), result in bit
7904       // if(!size && ifx), conditional oper: if(left & right)
7905       symbol *tlbl = newiTempLabel(NULL);
7906       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7907       if(size)
7908         pic16_emitcode("setb","c");
7909       while(sizer--){
7910         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7911         pic16_emitcode("anl","a,%s",
7912                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7913         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7914         offset++;
7915       }
7916       if(size){
7917         CLRC;
7918         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7919         pic16_outBitC(result);
7920       } else if(ifx)
7921         jmpTrueOrFalse(ifx, tlbl);
7922     } else {
7923       for(;(size--);offset++) {
7924         // normal case
7925         // result = left & right
7926         if(AOP_TYPE(right) == AOP_LIT){
7927           int t = (lit >> (offset*8)) & 0x0FFL;
7928           switch(t) { 
7929           case 0x00:
7930             pic16_emitcode("clrf","%s",
7931                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7932             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7933             break;
7934           case 0xff:
7935             pic16_emitcode("movf","%s,w",
7936                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7937             pic16_emitcode("movwf","%s",
7938                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7939             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7940             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7941             break;
7942           default:
7943             pic16_emitcode("movlw","0x%x",t);
7944             pic16_emitcode("andwf","%s,w",
7945                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7946             pic16_emitcode("movwf","%s",
7947                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7948               
7949             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7950             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7951             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7952           }
7953           continue;
7954         }
7955
7956         if (AOP_TYPE(left) == AOP_ACC) {
7957           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7958           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7959         } else {
7960           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7961           pic16_emitcode("andwf","%s,w",
7962                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7963           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7964           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7965         }
7966         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7967         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7968       }
7969     }
7970   }
7971
7972   release :
7973     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7974   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7975   pic16_freeAsmop(result,NULL,ic,TRUE);     
7976 }
7977
7978 /*-----------------------------------------------------------------*/
7979 /* genOr  - code for or                                            */
7980 /*-----------------------------------------------------------------*/
7981 static void genOr (iCode *ic, iCode *ifx)
7982 {
7983     operand *left, *right, *result;
7984     int size, offset=0;
7985     unsigned long lit = 0L;
7986
7987     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7988
7989     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7990     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7991     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7992
7993     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7994
7995     /* if left is a literal & right is not then exchange them */
7996     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7997         AOP_NEEDSACC(left)) {
7998         operand *tmp = right ;
7999         right = left;
8000         left = tmp;
8001     }
8002
8003     /* if result = right then exchange them */
8004     if(pic16_sameRegs(AOP(result),AOP(right))){
8005         operand *tmp = right ;
8006         right = left;
8007         left = tmp;
8008     }
8009
8010     /* if right is bit then exchange them */
8011     if (AOP_TYPE(right) == AOP_CRY &&
8012         AOP_TYPE(left) != AOP_CRY){
8013         operand *tmp = right ;
8014         right = left;
8015         left = tmp;
8016     }
8017
8018     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8019
8020     if(AOP_TYPE(right) == AOP_LIT)
8021         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8022
8023     size = AOP_SIZE(result);
8024
8025     // if(bit | yy)
8026     // xx = bit | yy;
8027     if (AOP_TYPE(left) == AOP_CRY){
8028         if(AOP_TYPE(right) == AOP_LIT){
8029             // c = bit & literal;
8030             if(lit){
8031                 // lit != 0 => result = 1
8032                 if(AOP_TYPE(result) == AOP_CRY){
8033                   if(size)
8034                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8035                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8036                   //     AOP(result)->aopu.aop_dir,
8037                   //     AOP(result)->aopu.aop_dir);
8038                     else if(ifx)
8039                         continueIfTrue(ifx);
8040                     goto release;
8041                 }
8042             } else {
8043                 // lit == 0 => result = left
8044                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8045                     goto release;
8046                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8047             }
8048         } else {
8049             if (AOP_TYPE(right) == AOP_CRY){
8050               if(pic16_sameRegs(AOP(result),AOP(left))){
8051                 // c = bit | bit;
8052                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8053                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8054                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8055
8056                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8057                          AOP(result)->aopu.aop_dir,
8058                          AOP(result)->aopu.aop_dir);
8059                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8060                          AOP(right)->aopu.aop_dir,
8061                          AOP(right)->aopu.aop_dir);
8062                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8063                          AOP(result)->aopu.aop_dir,
8064                          AOP(result)->aopu.aop_dir);
8065               } else {
8066                 if( AOP_TYPE(result) == AOP_ACC) {
8067                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8068                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8069                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8070                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8071
8072                 } else {
8073
8074                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8075                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8076                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8077                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8078
8079                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8080                                  AOP(result)->aopu.aop_dir,
8081                                  AOP(result)->aopu.aop_dir);
8082                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8083                                  AOP(right)->aopu.aop_dir,
8084                                  AOP(right)->aopu.aop_dir);
8085                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8086                                  AOP(left)->aopu.aop_dir,
8087                                  AOP(left)->aopu.aop_dir);
8088                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8089                                  AOP(result)->aopu.aop_dir,
8090                                  AOP(result)->aopu.aop_dir);
8091                 }
8092               }
8093             } else {
8094                 // c = bit | val;
8095                 symbol *tlbl = newiTempLabel(NULL);
8096                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8097
8098
8099                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8100                 if( AOP_TYPE(right) == AOP_ACC) {
8101                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8102                   emitSKPNZ;
8103                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8104                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8105                 }
8106
8107
8108
8109                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8110                     pic16_emitcode(";XXX setb","c");
8111                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8112                          AOP(left)->aopu.aop_dir,tlbl->key+100);
8113                 pic16_toBoolean(right);
8114                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8115                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8116                     jmpTrueOrFalse(ifx, tlbl);
8117                     goto release;
8118                 } else {
8119                     CLRC;
8120                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8121                 }
8122             }
8123         }
8124         // bit = c
8125         // val = c
8126         if(size)
8127             pic16_outBitC(result);
8128         // if(bit | ...)
8129         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8130             genIfxJump(ifx, "c");           
8131         goto release ;
8132     }
8133
8134     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
8135     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
8136     if((AOP_TYPE(right) == AOP_LIT) &&
8137        (AOP_TYPE(result) == AOP_CRY) &&
8138        (AOP_TYPE(left) != AOP_CRY)){
8139         if(lit){
8140           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8141             // result = 1
8142             if(size)
8143                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8144             else 
8145                 continueIfTrue(ifx);
8146             goto release;
8147         } else {
8148           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8149             // lit = 0, result = boolean(left)
8150             if(size)
8151                 pic16_emitcode(";XXX setb","c");
8152             pic16_toBoolean(right);
8153             if(size){
8154                 symbol *tlbl = newiTempLabel(NULL);
8155                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8156                 CLRC;
8157                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8158             } else {
8159                 genIfxJump (ifx,"a");
8160                 goto release;
8161             }
8162         }
8163         pic16_outBitC(result);
8164         goto release ;
8165     }
8166
8167     /* if left is same as result */
8168     if(pic16_sameRegs(AOP(result),AOP(left))){
8169       int know_W = -1;
8170       for(;size--; offset++,lit>>=8) {
8171         if(AOP_TYPE(right) == AOP_LIT){
8172           if((lit & 0xff) == 0)
8173             /*  or'ing with 0 has no effect */
8174             continue;
8175           else {
8176             int p = pic16_my_powof2(lit & 0xff);
8177             if(p>=0) {
8178               /* only one bit is set in the literal, so use a bsf instruction */
8179               pic16_emitpcode(POC_BSF,
8180                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8181             } else {
8182               if(know_W != (lit & 0xff))
8183                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8184               know_W = lit & 0xff;
8185               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8186             }
8187                     
8188           }
8189         } else {
8190           if (AOP_TYPE(left) == AOP_ACC) {
8191             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
8192             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8193           } else {                  
8194             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8195             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
8196
8197             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8198             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8199
8200           }
8201         }
8202       }
8203     } else {
8204         // left & result in different registers
8205         if(AOP_TYPE(result) == AOP_CRY){
8206             // result = bit
8207             // if(size), result in bit
8208             // if(!size && ifx), conditional oper: if(left | right)
8209             symbol *tlbl = newiTempLabel(NULL);
8210             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8211             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8212
8213
8214             if(size)
8215                 pic16_emitcode(";XXX setb","c");
8216             while(sizer--){
8217                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8218                 pic16_emitcode(";XXX orl","a,%s",
8219                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8220                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8221                 offset++;
8222             }
8223             if(size){
8224                 CLRC;
8225                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8226                 pic16_outBitC(result);
8227             } else if(ifx)
8228                 jmpTrueOrFalse(ifx, tlbl);
8229         } else for(;(size--);offset++){
8230           // normal case
8231           // result = left & right
8232           if(AOP_TYPE(right) == AOP_LIT){
8233             int t = (lit >> (offset*8)) & 0x0FFL;
8234             switch(t) { 
8235             case 0x00:
8236               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8237               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8238
8239               pic16_emitcode("movf","%s,w",
8240                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8241               pic16_emitcode("movwf","%s",
8242                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8243               break;
8244             default:
8245               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
8246               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8247               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8248
8249               pic16_emitcode("movlw","0x%x",t);
8250               pic16_emitcode("iorwf","%s,w",
8251                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8252               pic16_emitcode("movwf","%s",
8253                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8254               
8255             }
8256             continue;
8257           }
8258
8259           // faster than result <- left, anl result,right
8260           // and better if result is SFR
8261           if (AOP_TYPE(left) == AOP_ACC) {
8262             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
8263             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8264           } else {
8265             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8266             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8267
8268             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8269             pic16_emitcode("iorwf","%s,w",
8270                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8271           }
8272           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8273           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8274         }
8275     }
8276
8277 release :
8278     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8279     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8280     pic16_freeAsmop(result,NULL,ic,TRUE);     
8281 }
8282
8283 /*-----------------------------------------------------------------*/
8284 /* genXor - code for xclusive or                                   */
8285 /*-----------------------------------------------------------------*/
8286 static void genXor (iCode *ic, iCode *ifx)
8287 {
8288   operand *left, *right, *result;
8289   int size, offset=0;
8290   unsigned long lit = 0L;
8291
8292   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8293
8294   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8295   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8296   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8297
8298   /* if left is a literal & right is not ||
8299      if left needs acc & right does not */
8300   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8301       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8302     operand *tmp = right ;
8303     right = left;
8304     left = tmp;
8305   }
8306
8307   /* if result = right then exchange them */
8308   if(pic16_sameRegs(AOP(result),AOP(right))){
8309     operand *tmp = right ;
8310     right = left;
8311     left = tmp;
8312   }
8313
8314   /* if right is bit then exchange them */
8315   if (AOP_TYPE(right) == AOP_CRY &&
8316       AOP_TYPE(left) != AOP_CRY){
8317     operand *tmp = right ;
8318     right = left;
8319     left = tmp;
8320   }
8321   if(AOP_TYPE(right) == AOP_LIT)
8322     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8323
8324   size = AOP_SIZE(result);
8325
8326   // if(bit ^ yy)
8327   // xx = bit ^ yy;
8328   if (AOP_TYPE(left) == AOP_CRY){
8329     if(AOP_TYPE(right) == AOP_LIT){
8330       // c = bit & literal;
8331       if(lit>>1){
8332         // lit>>1  != 0 => result = 1
8333         if(AOP_TYPE(result) == AOP_CRY){
8334           if(size)
8335             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8336             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8337           else if(ifx)
8338             continueIfTrue(ifx);
8339           goto release;
8340         }
8341         pic16_emitcode("setb","c");
8342       } else{
8343         // lit == (0 or 1)
8344         if(lit == 0){
8345           // lit == 0, result = left
8346           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8347             goto release;
8348           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8349         } else{
8350           // lit == 1, result = not(left)
8351           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8352             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8353             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8354             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8355             goto release;
8356           } else {
8357             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8358             pic16_emitcode("cpl","c");
8359           }
8360         }
8361       }
8362
8363     } else {
8364       // right != literal
8365       symbol *tlbl = newiTempLabel(NULL);
8366       if (AOP_TYPE(right) == AOP_CRY){
8367         // c = bit ^ bit;
8368         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8369       }
8370       else{
8371         int sizer = AOP_SIZE(right);
8372         // c = bit ^ val
8373         // if val>>1 != 0, result = 1
8374         pic16_emitcode("setb","c");
8375         while(sizer){
8376           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8377           if(sizer == 1)
8378             // test the msb of the lsb
8379             pic16_emitcode("anl","a,#0xfe");
8380           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8381           sizer--;
8382         }
8383         // val = (0,1)
8384         pic16_emitcode("rrc","a");
8385       }
8386       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8387       pic16_emitcode("cpl","c");
8388       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8389     }
8390     // bit = c
8391     // val = c
8392     if(size)
8393       pic16_outBitC(result);
8394     // if(bit | ...)
8395     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8396       genIfxJump(ifx, "c");           
8397     goto release ;
8398   }
8399
8400   if(pic16_sameRegs(AOP(result),AOP(left))){
8401     /* if left is same as result */
8402     for(;size--; offset++) {
8403       if(AOP_TYPE(right) == AOP_LIT){
8404         int t  = (lit >> (offset*8)) & 0x0FFL;
8405         if(t == 0x00L)
8406           continue;
8407         else
8408           if (IS_AOP_PREG(left)) {
8409             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8410             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8411             pic16_aopPut(AOP(result),"a",offset);
8412           } else {
8413             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8414             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8415             pic16_emitcode("xrl","%s,%s",
8416                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8417                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8418           }
8419       } else {
8420         if (AOP_TYPE(left) == AOP_ACC)
8421           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8422         else {
8423           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8424           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8425 /*
8426           if (IS_AOP_PREG(left)) {
8427             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8428             pic16_aopPut(AOP(result),"a",offset);
8429           } else
8430             pic16_emitcode("xrl","%s,a",
8431                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8432 */
8433         }
8434       }
8435     }
8436   } else {
8437     // left & result in different registers
8438     if(AOP_TYPE(result) == AOP_CRY){
8439       // result = bit
8440       // if(size), result in bit
8441       // if(!size && ifx), conditional oper: if(left ^ right)
8442       symbol *tlbl = newiTempLabel(NULL);
8443       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8444       if(size)
8445         pic16_emitcode("setb","c");
8446       while(sizer--){
8447         if((AOP_TYPE(right) == AOP_LIT) &&
8448            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8449           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8450         } else {
8451           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8452           pic16_emitcode("xrl","a,%s",
8453                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8454         }
8455         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8456         offset++;
8457       }
8458       if(size){
8459         CLRC;
8460         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8461         pic16_outBitC(result);
8462       } else if(ifx)
8463         jmpTrueOrFalse(ifx, tlbl);
8464     } else for(;(size--);offset++){
8465       // normal case
8466       // result = left & right
8467       if(AOP_TYPE(right) == AOP_LIT){
8468         int t = (lit >> (offset*8)) & 0x0FFL;
8469         switch(t) { 
8470         case 0x00:
8471           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8472           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8473           pic16_emitcode("movf","%s,w",
8474                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8475           pic16_emitcode("movwf","%s",
8476                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8477           break;
8478         case 0xff:
8479           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8480           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8481           pic16_emitcode("comf","%s,w",
8482                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8483           pic16_emitcode("movwf","%s",
8484                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8485           break;
8486         default:
8487           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8488           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8489           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8490           pic16_emitcode("movlw","0x%x",t);
8491           pic16_emitcode("xorwf","%s,w",
8492                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8493           pic16_emitcode("movwf","%s",
8494                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8495
8496         }
8497         continue;
8498       }
8499
8500       // faster than result <- left, anl result,right
8501       // and better if result is SFR
8502       if (AOP_TYPE(left) == AOP_ACC) {
8503         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8504         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8505       } else {
8506         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8507         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8508         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8509         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8510       }
8511       if ( AOP_TYPE(result) != AOP_ACC){
8512         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8513         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8514       }
8515     }
8516   }
8517
8518   release :
8519     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8520   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8521   pic16_freeAsmop(result,NULL,ic,TRUE);     
8522 }
8523
8524 /*-----------------------------------------------------------------*/
8525 /* genInline - write the inline code out                           */
8526 /*-----------------------------------------------------------------*/
8527 static void genInline (iCode *ic)
8528 {
8529   char *buffer, *bp, *bp1;
8530     
8531         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8532
8533         _G.inLine += (!options.asmpeep);
8534
8535         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8536         strcpy(buffer,IC_INLINE(ic));
8537
8538 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
8539
8540         /* emit each line as a code */
8541         while (*bp) {
8542                 if (*bp == '\n') {
8543                         *bp++ = '\0';
8544
8545                         if(*bp1)
8546                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8547                         bp1 = bp;
8548                 } else {
8549                         if (*bp == ':') {
8550                                 bp++;
8551                                 *bp = '\0';
8552                                 bp++;
8553
8554                                 /* print label, use this special format with NULL directive
8555                                  * to denote that the argument should not be indented with tab */
8556                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8557                                 bp1 = bp;
8558                         } else
8559                                 bp++;
8560                 }
8561         }
8562
8563         if ((bp1 != bp) && *bp1)
8564                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8565
8566
8567     Safe_free(buffer);
8568
8569     _G.inLine -= (!options.asmpeep);
8570 }
8571
8572 /*-----------------------------------------------------------------*/
8573 /* genRRC - rotate right with carry                                */
8574 /*-----------------------------------------------------------------*/
8575 static void genRRC (iCode *ic)
8576 {
8577   operand *left , *result ;
8578   int size, offset = 0, same;
8579
8580   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8581
8582   /* rotate right with carry */
8583   left = IC_LEFT(ic);
8584   result=IC_RESULT(ic);
8585   pic16_aopOp (left,ic,FALSE);
8586   pic16_aopOp (result,ic,FALSE);
8587
8588   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8589
8590   same = pic16_sameRegs(AOP(result),AOP(left));
8591
8592   size = AOP_SIZE(result);    
8593
8594   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8595
8596   /* get the lsb and put it into the carry */
8597   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8598
8599   offset = 0 ;
8600
8601   while(size--) {
8602
8603     if(same) {
8604       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8605     } else {
8606       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8607       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8608     }
8609
8610     offset++;
8611   }
8612
8613   pic16_freeAsmop(left,NULL,ic,TRUE);
8614   pic16_freeAsmop(result,NULL,ic,TRUE);
8615 }
8616
8617 /*-----------------------------------------------------------------*/
8618 /* genRLC - generate code for rotate left with carry               */
8619 /*-----------------------------------------------------------------*/
8620 static void genRLC (iCode *ic)
8621 {    
8622   operand *left , *result ;
8623   int size, offset = 0;
8624   int same;
8625
8626   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8627   /* rotate right with carry */
8628   left = IC_LEFT(ic);
8629   result=IC_RESULT(ic);
8630   pic16_aopOp (left,ic,FALSE);
8631   pic16_aopOp (result,ic,FALSE);
8632
8633   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8634
8635   same = pic16_sameRegs(AOP(result),AOP(left));
8636
8637   /* move it to the result */
8638   size = AOP_SIZE(result);    
8639
8640   /* get the msb and put it into the carry */
8641   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8642
8643   offset = 0 ;
8644
8645   while(size--) {
8646
8647     if(same) {
8648       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8649     } else {
8650       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8651       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8652     }
8653
8654     offset++;
8655   }
8656
8657
8658   pic16_freeAsmop(left,NULL,ic,TRUE);
8659   pic16_freeAsmop(result,NULL,ic,TRUE);
8660 }
8661
8662
8663 /* gpasm can get the highest order bit with HIGH/UPPER
8664  * so the following probably is not needed -- VR */
8665  
8666 /*-----------------------------------------------------------------*/
8667 /* genGetHbit - generates code get highest order bit               */
8668 /*-----------------------------------------------------------------*/
8669 static void genGetHbit (iCode *ic)
8670 {
8671     operand *left, *result;
8672     left = IC_LEFT(ic);
8673     result=IC_RESULT(ic);
8674     pic16_aopOp (left,ic,FALSE);
8675     pic16_aopOp (result,ic,FALSE);
8676
8677     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8678     /* get the highest order byte into a */
8679     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8680     if(AOP_TYPE(result) == AOP_CRY){
8681         pic16_emitcode("rlc","a");
8682         pic16_outBitC(result);
8683     }
8684     else{
8685         pic16_emitcode("rl","a");
8686         pic16_emitcode("anl","a,#0x01");
8687         pic16_outAcc(result);
8688     }
8689
8690
8691     pic16_freeAsmop(left,NULL,ic,TRUE);
8692     pic16_freeAsmop(result,NULL,ic,TRUE);
8693 }
8694
8695 #if 0
8696 /*-----------------------------------------------------------------*/
8697 /* AccRol - rotate left accumulator by known count                 */
8698 /*-----------------------------------------------------------------*/
8699 static void AccRol (int shCount)
8700 {
8701     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8702     shCount &= 0x0007;              // shCount : 0..7
8703     switch(shCount){
8704         case 0 :
8705             break;
8706         case 1 :
8707             pic16_emitcode("rl","a");
8708             break;
8709         case 2 :
8710             pic16_emitcode("rl","a");
8711             pic16_emitcode("rl","a");
8712             break;
8713         case 3 :
8714             pic16_emitcode("swap","a");
8715             pic16_emitcode("rr","a");
8716             break;
8717         case 4 :
8718             pic16_emitcode("swap","a");
8719             break;
8720         case 5 :
8721             pic16_emitcode("swap","a");
8722             pic16_emitcode("rl","a");
8723             break;
8724         case 6 :
8725             pic16_emitcode("rr","a");
8726             pic16_emitcode("rr","a");
8727             break;
8728         case 7 :
8729             pic16_emitcode("rr","a");
8730             break;
8731     }
8732 }
8733 #endif
8734
8735 /*-----------------------------------------------------------------*/
8736 /* AccLsh - left shift accumulator by known count                  */
8737 /*-----------------------------------------------------------------*/
8738 static void AccLsh (int shCount)
8739 {
8740         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8741         switch(shCount){
8742                 case 0 :
8743                         return;
8744                         break;
8745                 case 1 :
8746                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8747                         break;
8748                 case 2 :
8749                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8750                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8751                         break;
8752                 case 3 :
8753                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8754                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8755                         break;
8756                 case 4 :
8757                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8758                         break;
8759                 case 5 :
8760                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8761                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8762                         break;
8763                 case 6 :
8764                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8765                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8766                         break;
8767                 case 7 :
8768                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8769                         break;
8770         }
8771
8772         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8773 }
8774
8775 /*-----------------------------------------------------------------*/
8776 /* AccRsh - right shift accumulator by known count                 */
8777 /*-----------------------------------------------------------------*/
8778 static void AccRsh (int shCount, int andmask)
8779 {
8780         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8781         switch(shCount){
8782                 case 0 :
8783                         return; break;
8784                 case 1 :
8785                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8786                         break;
8787                 case 2 :
8788                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8789                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8790                         break;
8791                 case 3 :
8792                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8793                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8794                         break;
8795                 case 4 :
8796                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8797                         break;
8798                 case 5 :
8799                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8800                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8801                         break;
8802                 case 6 :
8803                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8804                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8805                         break;
8806                 case 7 :
8807                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8808                         break;
8809         }
8810         
8811         if(andmask)
8812                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8813         else
8814                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8815 }
8816
8817 #if 0
8818 /*-----------------------------------------------------------------*/
8819 /* AccSRsh - signed right shift accumulator by known count                 */
8820 /*-----------------------------------------------------------------*/
8821 static void AccSRsh (int shCount)
8822 {
8823     symbol *tlbl ;
8824     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8825     if(shCount != 0){
8826         if(shCount == 1){
8827             pic16_emitcode("mov","c,acc.7");
8828             pic16_emitcode("rrc","a");
8829         } else if(shCount == 2){
8830             pic16_emitcode("mov","c,acc.7");
8831             pic16_emitcode("rrc","a");
8832             pic16_emitcode("mov","c,acc.7");
8833             pic16_emitcode("rrc","a");
8834         } else {
8835             tlbl = newiTempLabel(NULL);
8836             /* rotate right accumulator */
8837             AccRol(8 - shCount);
8838             /* and kill the higher order bits */
8839             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8840             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8841             pic16_emitcode("orl","a,#0x%02x",
8842                      (unsigned char)~SRMask[shCount]);
8843             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8844         }
8845     }
8846 }
8847 #endif
8848
8849 /*-----------------------------------------------------------------*/
8850 /* shiftR1Left2Result - shift right one byte from left to result   */
8851 /*-----------------------------------------------------------------*/
8852 static void shiftR1Left2ResultSigned (operand *left, int offl,
8853                                 operand *result, int offr,
8854                                 int shCount)
8855 {
8856   int same;
8857
8858   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8859
8860   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8861
8862   switch(shCount) {
8863   case 1:
8864     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8865     if(same) 
8866       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8867     else {
8868       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8869       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8870     }
8871
8872     break;
8873   case 2:
8874
8875     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8876     if(same) 
8877       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8878     else {
8879       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8880       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8881     }
8882     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8883     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8884
8885     break;
8886
8887   case 3:
8888     if(same)
8889       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8890     else {
8891       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8892       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8893     }
8894
8895     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8896     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8897     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8898
8899     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8900     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8901
8902     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8903     break;
8904
8905   case 4:
8906     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8907     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8908     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8909     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8910     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8911     break;
8912   case 5:
8913     if(same) {
8914       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8915     } else {
8916       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8917       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8918     }
8919     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8920     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8921     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8922     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8923     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8924     break;
8925
8926   case 6:
8927     if(same) {
8928       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8929       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8930       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8931       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8932       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8933       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8934     } else {
8935       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8936       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8937       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8938       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8939       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8940     }
8941     break;
8942
8943   case 7:
8944     if(same) {
8945       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8946       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8947       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8948       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8949     } else {
8950       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8951       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8952       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8953     }
8954
8955   default:
8956     break;
8957   }
8958 }
8959
8960 /*-----------------------------------------------------------------*/
8961 /* shiftR1Left2Result - shift right one byte from left to result   */
8962 /*-----------------------------------------------------------------*/
8963 static void shiftR1Left2Result (operand *left, int offl,
8964                                 operand *result, int offr,
8965                                 int shCount, int sign)
8966 {
8967   int same;
8968
8969   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8970
8971   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8972
8973   /* Copy the msb into the carry if signed. */
8974   if(sign) {
8975     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8976     return;
8977   }
8978
8979
8980
8981   switch(shCount) {
8982   case 1:
8983     emitCLRC;
8984     if(same) 
8985       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8986     else {
8987       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8988       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8989     }
8990     break;
8991   case 2:
8992     emitCLRC;
8993     if(same) {
8994       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8995     } else {
8996       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8997       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8998     }
8999     emitCLRC;
9000     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9001
9002     break;
9003   case 3:
9004     if(same)
9005       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9006     else {
9007       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9008       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9009     }
9010
9011     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
9012     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
9013     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9014     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9015     break;
9016       
9017   case 4:
9018     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9019     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9020     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9021     break;
9022
9023   case 5:
9024     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9025     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9026     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9027     //emitCLRC;
9028     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9029
9030     break;
9031   case 6:
9032
9033     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
9034     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9035     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9036     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
9037     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
9038     break;
9039
9040   case 7:
9041
9042     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9043     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9044     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9045
9046     break;
9047
9048   default:
9049     break;
9050   }
9051 }
9052
9053 /*-----------------------------------------------------------------*/
9054 /* shiftL1Left2Result - shift left one byte from left to result    */
9055 /*-----------------------------------------------------------------*/
9056 static void shiftL1Left2Result (operand *left, int offl,
9057                                 operand *result, int offr, int shCount)
9058 {
9059   int same;
9060
9061   //    char *l;
9062   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9063
9064   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9065   DEBUGpic16_emitcode ("; ***","same =  %d",same);
9066     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9067     //    MOVA(l);
9068     /* shift left accumulator */
9069     //AccLsh(shCount); // don't comment out just yet...
9070   //    pic16_aopPut(AOP(result),"a",offr);
9071
9072   switch(shCount) {
9073   case 1:
9074     /* Shift left 1 bit position */
9075     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9076     if(same) {
9077       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9078     } else {
9079       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9080       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9081     }
9082     break;
9083   case 2:
9084     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9085     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9086     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9087     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9088     break;
9089   case 3:
9090     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9091     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9092     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9093     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9094     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9095     break;
9096   case 4:
9097     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9098     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9099     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9100     break;
9101   case 5:
9102     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9103     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9104     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9105     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9106     break;
9107   case 6:
9108     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9109     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9110     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9111     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9112     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9113     break;
9114   case 7:
9115     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9116     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9117     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9118     break;
9119
9120   default:
9121     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9122   }
9123
9124 }
9125
9126 /*-----------------------------------------------------------------*/
9127 /* movLeft2Result - move byte from left to result                  */
9128 /*-----------------------------------------------------------------*/
9129 static void movLeft2Result (operand *left, int offl,
9130                             operand *result, int offr)
9131 {
9132   char *l;
9133   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9134   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9135     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9136
9137     if (*l == '@' && (IS_AOP_PREG(result))) {
9138       pic16_emitcode("mov","a,%s",l);
9139       pic16_aopPut(AOP(result),"a",offr);
9140     } else {
9141       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9142       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9143     }
9144   }
9145 }
9146
9147 /*-----------------------------------------------------------------*/
9148 /* shiftL2Left2Result - shift left two bytes from left to result   */
9149 /*-----------------------------------------------------------------*/
9150 static void shiftL2Left2Result (operand *left, int offl,
9151                                 operand *result, int offr, int shCount)
9152 {
9153   int same = pic16_sameRegs(AOP(result), AOP(left));
9154   int i;
9155
9156   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9157
9158   if (same && (offl != offr)) { // shift bytes
9159     if (offr > offl) {
9160        for(i=1;i>-1;i--) {
9161          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9162          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9163        }
9164     } else { // just treat as different later on
9165                 same = 0;
9166     }
9167   }
9168
9169   if(same) {
9170     switch(shCount) {
9171     case 0:
9172       break;
9173     case 1:
9174     case 2:
9175     case 3:
9176
9177       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9178       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9179       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9180
9181       while(--shCount) {
9182                 emitCLRC;
9183                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9184                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9185       }
9186
9187       break;
9188     case 4:
9189     case 5:
9190       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9191       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9192       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9193       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9194       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9195       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9196       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9197       if(shCount >=5) {
9198                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9199                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9200       }
9201       break;
9202     case 6:
9203       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9204       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9205       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9206       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9207       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9208       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9209       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9210       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9211       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9212       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9213       break;
9214     case 7:
9215       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9216       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9217       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9218       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9219       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9220     }
9221
9222   } else {
9223     switch(shCount) {
9224     case 0:
9225       break;
9226     case 1:
9227     case 2:
9228     case 3:
9229       /* note, use a mov/add for the shift since the mov has a
9230          chance of getting optimized out */
9231       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9232       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9233       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9234       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9235       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9236
9237       while(--shCount) {
9238                 emitCLRC;
9239                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9240                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9241       }
9242       break;
9243
9244     case 4:
9245     case 5:
9246       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9247       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9248       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9249       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9250       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9251       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9252       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9253       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9254
9255
9256       if(shCount == 5) {
9257                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9258                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9259       }
9260       break;
9261     case 6:
9262       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9263       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9264       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9265       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9266
9267       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9268       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9269       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9270       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9271       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9272       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9273       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9274       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9275       break;
9276     case 7:
9277       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9278       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9279       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9280       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9281       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9282     }
9283   }
9284
9285 }
9286 /*-----------------------------------------------------------------*/
9287 /* shiftR2Left2Result - shift right two bytes from left to result  */
9288 /*-----------------------------------------------------------------*/
9289 static void shiftR2Left2Result (operand *left, int offl,
9290                                 operand *result, int offr,
9291                                 int shCount, int sign)
9292 {
9293   int same = pic16_sameRegs(AOP(result), AOP(left));
9294   int i;
9295   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9296
9297   if (same && (offl != offr)) { // shift right bytes
9298     if (offr < offl) {
9299        for(i=0;i<2;i++) {
9300          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9301          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9302        }
9303     } else { // just treat as different later on
9304                 same = 0;
9305     }
9306   }
9307
9308   switch(shCount) {
9309   case 0:
9310     break;
9311   case 1:
9312   case 2:
9313   case 3:
9314     if(sign)
9315       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9316     else
9317       emitCLRC;
9318
9319     if(same) {
9320       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9321       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9322     } else {
9323       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9324       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9325       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9326       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9327     }
9328
9329     while(--shCount) {
9330       if(sign)
9331                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9332       else
9333                 emitCLRC;
9334       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9335       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9336     }
9337     break;
9338   case 4:
9339   case 5:
9340     if(same) {
9341
9342       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9343       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9344       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9345
9346       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9347       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9348       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9349       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9350     } else {
9351       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9352       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9353       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9354
9355       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9356       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9357       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9358       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9359       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9360     }
9361
9362     if(shCount >=5) {
9363       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9364       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9365     }
9366
9367     if(sign) {
9368       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9369       pic16_emitpcode(POC_BTFSC, 
9370                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9371       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9372     }
9373
9374     break;
9375
9376   case 6:
9377     if(same) {
9378
9379       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9380       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9381
9382       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9383       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9384       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9385       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9386       if(sign) {
9387         pic16_emitpcode(POC_BTFSC, 
9388                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9389         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9390       }
9391       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9392       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9393       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9394       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9395     } else {
9396       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9397       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9398       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9399       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9400       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9401       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9402       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9403       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9404       if(sign) {
9405         pic16_emitpcode(POC_BTFSC, 
9406                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9407         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9408       }
9409       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9410       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9411
9412         
9413     }
9414
9415     break;
9416   case 7:
9417     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9418     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9419     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9420     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9421     if(sign) {
9422       emitSKPNC;
9423       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9424     } else 
9425       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9426   }
9427 }
9428
9429
9430 /*-----------------------------------------------------------------*/
9431 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9432 /*-----------------------------------------------------------------*/
9433 static void shiftLLeftOrResult (operand *left, int offl,
9434                                 operand *result, int offr, int shCount)
9435 {
9436     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9437
9438     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9439     /* shift left accumulator */
9440     AccLsh(shCount);
9441     /* or with result */
9442     /* back to result */
9443     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9444 }
9445
9446 /*-----------------------------------------------------------------*/
9447 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9448 /*-----------------------------------------------------------------*/
9449 static void shiftRLeftOrResult (operand *left, int offl,
9450                                 operand *result, int offr, int shCount)
9451 {
9452     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9453     
9454     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9455     /* shift right accumulator */
9456     AccRsh(shCount, 1);
9457     /* or with result */
9458     /* back to result */
9459     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9460 }
9461
9462 /*-----------------------------------------------------------------*/
9463 /* genlshOne - left shift a one byte quantity by known count       */
9464 /*-----------------------------------------------------------------*/
9465 static void genlshOne (operand *result, operand *left, int shCount)
9466 {       
9467     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9468     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9469 }
9470
9471 /*-----------------------------------------------------------------*/
9472 /* genlshTwo - left shift two bytes by known amount != 0           */
9473 /*-----------------------------------------------------------------*/
9474 static void genlshTwo (operand *result,operand *left, int shCount)
9475 {
9476     int size;
9477     
9478     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9479     size = pic16_getDataSize(result);
9480
9481     /* if shCount >= 8 */
9482     if (shCount >= 8) {
9483         shCount -= 8 ;
9484
9485         if (size > 1){
9486             if (shCount)
9487                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9488             else 
9489                 movLeft2Result(left, LSB, result, MSB16);
9490         }
9491         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9492     }
9493
9494     /*  1 <= shCount <= 7 */
9495     else {  
9496         if(size == 1)
9497             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9498         else 
9499             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9500     }
9501 }
9502
9503 /*-----------------------------------------------------------------*/
9504 /* shiftLLong - shift left one long from left to result            */
9505 /* offr = LSB or MSB16                                             */
9506 /*-----------------------------------------------------------------*/
9507 static void shiftLLong (operand *left, operand *result, int offr )
9508 {
9509     int size = AOP_SIZE(result);
9510     int same = pic16_sameRegs(AOP(left),AOP(result));
9511         int i;
9512
9513     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9514
9515         if (same && (offr == MSB16)) { //shift one byte
9516                 for(i=size-1;i>=MSB16;i--) {
9517                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9518                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9519                 }
9520         } else {
9521                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9522         }
9523         
9524     if (size > LSB+offr ){
9525                 if (same) {
9526                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9527                 } else {
9528                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9529                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9530                 }
9531          }
9532
9533     if(size > MSB16+offr){
9534                 if (same) {
9535                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9536                 } else {
9537                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9538                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9539                 }
9540     }
9541
9542     if(size > MSB24+offr){
9543                 if (same) {
9544                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9545                 } else {
9546                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9547                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9548                 }
9549     }
9550
9551     if(size > MSB32+offr){
9552                 if (same) {
9553                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9554                 } else {
9555                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9556                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9557                 }
9558     }
9559     if(offr != LSB)
9560                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9561
9562 }
9563
9564 /*-----------------------------------------------------------------*/
9565 /* genlshFour - shift four byte by a known amount != 0             */
9566 /*-----------------------------------------------------------------*/
9567 static void genlshFour (operand *result, operand *left, int shCount)
9568 {
9569     int size;
9570
9571     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9572     size = AOP_SIZE(result);
9573
9574     /* if shifting more that 3 bytes */
9575     if (shCount >= 24 ) {
9576         shCount -= 24;
9577         if (shCount)
9578             /* lowest order of left goes to the highest
9579             order of the destination */
9580             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9581         else
9582             movLeft2Result(left, LSB, result, MSB32);
9583
9584                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9585                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9586                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9587
9588         return;
9589     }
9590
9591     /* more than two bytes */
9592     else if ( shCount >= 16 ) {
9593         /* lower order two bytes goes to higher order two bytes */
9594         shCount -= 16;
9595         /* if some more remaining */
9596         if (shCount)
9597             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9598         else {
9599             movLeft2Result(left, MSB16, result, MSB32);
9600             movLeft2Result(left, LSB, result, MSB24);
9601         }
9602                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9603                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9604         return;
9605     }    
9606
9607     /* if more than 1 byte */
9608     else if ( shCount >= 8 ) {
9609         /* lower order three bytes goes to higher order  three bytes */
9610         shCount -= 8;
9611         if(size == 2){
9612             if(shCount)
9613                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9614             else
9615                 movLeft2Result(left, LSB, result, MSB16);
9616         }
9617         else{   /* size = 4 */
9618             if(shCount == 0){
9619                 movLeft2Result(left, MSB24, result, MSB32);
9620                 movLeft2Result(left, MSB16, result, MSB24);
9621                 movLeft2Result(left, LSB, result, MSB16);
9622                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9623             }
9624             else if(shCount == 1)
9625                 shiftLLong(left, result, MSB16);
9626             else{
9627                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9628                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9629                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9630                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9631             }
9632         }
9633     }
9634
9635     /* 1 <= shCount <= 7 */
9636     else if(shCount <= 3)
9637     { 
9638         shiftLLong(left, result, LSB);
9639         while(--shCount >= 1)
9640             shiftLLong(result, result, LSB);
9641     }
9642     /* 3 <= shCount <= 7, optimize */
9643     else{
9644         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9645         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9646         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9647     }
9648 }
9649
9650 /*-----------------------------------------------------------------*/
9651 /* genLeftShiftLiteral - left shifting by known count              */
9652 /*-----------------------------------------------------------------*/
9653 void pic16_genLeftShiftLiteral (operand *left,
9654                                  operand *right,
9655                                  operand *result,
9656                                  iCode *ic)
9657 {    
9658     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9659     int size;
9660
9661     FENTRY;
9662     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9663     pic16_freeAsmop(right,NULL,ic,TRUE);
9664
9665     pic16_aopOp(left,ic,FALSE);
9666     pic16_aopOp(result,ic,FALSE);
9667
9668     size = getSize(operandType(result));
9669
9670 #if VIEW_SIZE
9671     pic16_emitcode("; shift left ","result %d, left %d",size,
9672              AOP_SIZE(left));
9673 #endif
9674
9675     /* I suppose that the left size >= result size */
9676     if(shCount == 0){
9677         while(size--){
9678             movLeft2Result(left, size, result, size);
9679         }
9680     }
9681
9682     else if(shCount >= (size * 8))
9683         while(size--)
9684             pic16_aopPut(AOP(result),zero,size);
9685     else{
9686         switch (size) {
9687             case 1:
9688                 genlshOne (result,left,shCount);
9689                 break;
9690
9691             case 2:
9692             case 3:
9693                 genlshTwo (result,left,shCount);
9694                 break;
9695
9696             case 4:
9697                 genlshFour (result,left,shCount);
9698                 break;
9699         }
9700     }
9701     pic16_freeAsmop(left,NULL,ic,TRUE);
9702     pic16_freeAsmop(result,NULL,ic,TRUE);
9703 }
9704
9705 /*-----------------------------------------------------------------*
9706  * genMultiAsm - repeat assembly instruction for size of register.
9707  * if endian == 1, then the high byte (i.e base address + size of 
9708  * register) is used first else the low byte is used first;
9709  *-----------------------------------------------------------------*/
9710 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9711 {
9712
9713   int offset = 0;
9714
9715   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9716
9717   if(!reg)
9718     return;
9719
9720   if(!endian) {
9721     endian = 1;
9722   } else {
9723     endian = -1;
9724     offset = size-1;
9725   }
9726
9727   while(size--) {
9728     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9729     offset += endian;
9730   }
9731
9732 }
9733
9734 #if !(USE_GENERIC_SIGNED_SHIFT)
9735 /*-----------------------------------------------------------------*/
9736 /* genLeftShift - generates code for left shifting                 */
9737 /*-----------------------------------------------------------------*/
9738 static void genLeftShift (iCode *ic)
9739 {
9740   operand *left,*right, *result;
9741   int size, offset;
9742 //  char *l;
9743   symbol *tlbl , *tlbl1;
9744   pCodeOp *pctemp;
9745
9746   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9747
9748   right = IC_RIGHT(ic);
9749   left  = IC_LEFT(ic);
9750   result = IC_RESULT(ic);
9751
9752   pic16_aopOp(right,ic,FALSE);
9753
9754   /* if the shift count is known then do it 
9755      as efficiently as possible */
9756   if (AOP_TYPE(right) == AOP_LIT) {
9757     pic16_genLeftShiftLiteral (left,right,result,ic);
9758     return ;
9759   }
9760
9761   /* shift count is unknown then we have to form
9762    * a loop. Get the loop count in WREG : Note: we take
9763    * only the lower order byte since shifting
9764    * more than 32 bits make no sense anyway, ( the
9765    * largest size of an object can be only 32 bits ) */
9766   
9767   pic16_aopOp(left,ic,FALSE);
9768   pic16_aopOp(result,ic,FALSE);
9769
9770   /* now move the left to the result if they are not the
9771    * same, and if size > 1,
9772    * and if right is not same to result (!!!) -- VR */
9773   if (!pic16_sameRegs(AOP(left),AOP(result))
9774       && (AOP_SIZE(result) > 1)) {
9775
9776     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9777
9778     size = AOP_SIZE(result);
9779     offset=0;
9780     while (size--) {
9781
9782 #if 0
9783       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9784       if (*l == '@' && (IS_AOP_PREG(result))) {
9785
9786           pic16_emitcode("mov","a,%s",l);
9787           pic16_aopPut(AOP(result),"a",offset);
9788       } else
9789 #endif
9790       {
9791         /* we don't know if left is a literal or a register, take care -- VR */
9792         mov2f(AOP(result), AOP(left), offset);
9793       }
9794       offset++;
9795     }
9796   }
9797
9798   size = AOP_SIZE(result);
9799
9800   /* if it is only one byte then */
9801   if (size == 1) {
9802     if(optimized_for_speed) {
9803       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9804       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9805       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9806       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9807       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9808       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9809       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9810       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9811       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9812       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9813       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9814       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9815     } else {
9816
9817       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9818
9819       tlbl = newiTempLabel(NULL);
9820
9821 #if 1
9822       /* this is already done, why change it? */
9823       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9824                 mov2f(AOP(result), AOP(left), 0);
9825       }
9826 #endif
9827
9828       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9829       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9830       pic16_emitpLabel(tlbl->key);
9831       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9832       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9833       emitSKPC;
9834       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9835     }
9836     goto release ;
9837   }
9838     
9839   if (pic16_sameRegs(AOP(left),AOP(result))) {
9840
9841     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9842     
9843     tlbl = newiTempLabel(NULL);
9844     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9845     genMultiAsm(POC_RRCF, result, size,1);
9846     pic16_emitpLabel(tlbl->key);
9847     genMultiAsm(POC_RLCF, result, size,0);
9848     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9849     emitSKPC;
9850     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9851     goto release;
9852   }
9853
9854   //tlbl = newiTempLabel(NULL);
9855   //offset = 0 ;   
9856   //tlbl1 = newiTempLabel(NULL);
9857
9858   //reAdjustPreg(AOP(result));    
9859     
9860   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9861   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9862   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9863   //MOVA(l);
9864   //pic16_emitcode("add","a,acc");         
9865   //pic16_aopPut(AOP(result),"a",offset++);
9866   //while (--size) {
9867   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9868   //  MOVA(l);
9869   //  pic16_emitcode("rlc","a");         
9870   //  pic16_aopPut(AOP(result),"a",offset++);
9871   //}
9872   //reAdjustPreg(AOP(result));
9873
9874   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9875   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9876
9877
9878   tlbl = newiTempLabel(NULL);
9879   tlbl1= newiTempLabel(NULL);
9880
9881   size = AOP_SIZE(result);
9882   offset = 1;
9883
9884   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9885
9886   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9887
9888   /* offset should be 0, 1 or 3 */
9889   
9890   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9891   emitSKPNZ;
9892   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9893
9894   pic16_emitpcode(POC_MOVWF, pctemp);
9895
9896
9897   pic16_emitpLabel(tlbl->key);
9898
9899   emitCLRC;
9900   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9901   while(--size)
9902     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9903
9904   pic16_emitpcode(POC_DECFSZ,  pctemp);
9905   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9906   pic16_emitpLabel(tlbl1->key);
9907
9908   pic16_popReleaseTempReg(pctemp,1);
9909
9910
9911  release:
9912   pic16_freeAsmop (right,NULL,ic,TRUE);
9913   pic16_freeAsmop(left,NULL,ic,TRUE);
9914   pic16_freeAsmop(result,NULL,ic,TRUE);
9915 }
9916 #endif
9917
9918
9919 #if 0
9920 #error old code (left here for reference)
9921 /*-----------------------------------------------------------------*/
9922 /* genLeftShift - generates code for left shifting                 */
9923 /*-----------------------------------------------------------------*/
9924 static void genLeftShift (iCode *ic)
9925 {
9926   operand *left,*right, *result;
9927   int size, offset;
9928   char *l;
9929   symbol *tlbl , *tlbl1;
9930   pCodeOp *pctemp;
9931
9932   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9933
9934   right = IC_RIGHT(ic);
9935   left  = IC_LEFT(ic);
9936   result = IC_RESULT(ic);
9937
9938   pic16_aopOp(right,ic,FALSE);
9939
9940   /* if the shift count is known then do it 
9941      as efficiently as possible */
9942   if (AOP_TYPE(right) == AOP_LIT) {
9943     pic16_genLeftShiftLiteral (left,right,result,ic);
9944     return ;
9945   }
9946
9947   /* shift count is unknown then we have to form 
9948      a loop get the loop count in B : Note: we take
9949      only the lower order byte since shifting
9950      more that 32 bits make no sense anyway, ( the
9951      largest size of an object can be only 32 bits ) */  
9952
9953     
9954   pic16_aopOp(left,ic,FALSE);
9955   pic16_aopOp(result,ic,FALSE);
9956
9957   /* now move the left to the result if they are not the
9958      same */
9959   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9960       AOP_SIZE(result) > 1) {
9961
9962     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9963
9964     size = AOP_SIZE(result);
9965     offset=0;
9966     while (size--) {
9967       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9968       if (*l == '@' && (IS_AOP_PREG(result))) {
9969
9970         pic16_emitcode("mov","a,%s",l);
9971         pic16_aopPut(AOP(result),"a",offset);
9972       } else {
9973
9974         /* we don't know if left is a literal or a register, take care -- VR */
9975         mov2f(AOP(result), AOP(left), offset);
9976       }
9977       offset++;
9978     }
9979   }
9980
9981   size = AOP_SIZE(result);
9982
9983   /* if it is only one byte then */
9984   if (size == 1) {
9985     if(optimized_for_speed) {
9986       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9987       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9988       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9989       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9990       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9991       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9992       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9993       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9994       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9995       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9996       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9997       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9998     } else {
9999
10000       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10001
10002       tlbl = newiTempLabel(NULL);
10003       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10004                 mov2f(AOP(result), AOP(left), 0);
10005                 
10006 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10007 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10008       }
10009
10010       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10011       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10012       pic16_emitpLabel(tlbl->key);
10013       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10014       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10015       emitSKPC;
10016       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10017     }
10018     goto release ;
10019   }
10020     
10021   if (pic16_sameRegs(AOP(left),AOP(result))) {
10022
10023     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10024     
10025     tlbl = newiTempLabel(NULL);
10026     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10027     genMultiAsm(POC_RRCF, result, size,1);
10028     pic16_emitpLabel(tlbl->key);
10029     genMultiAsm(POC_RLCF, result, size,0);
10030     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10031     emitSKPC;
10032     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10033     goto release;
10034   }
10035
10036   //tlbl = newiTempLabel(NULL);
10037   //offset = 0 ;   
10038   //tlbl1 = newiTempLabel(NULL);
10039
10040   //reAdjustPreg(AOP(result));    
10041     
10042   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
10043   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10044   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10045   //MOVA(l);
10046   //pic16_emitcode("add","a,acc");         
10047   //pic16_aopPut(AOP(result),"a",offset++);
10048   //while (--size) {
10049   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10050   //  MOVA(l);
10051   //  pic16_emitcode("rlc","a");         
10052   //  pic16_aopPut(AOP(result),"a",offset++);
10053   //}
10054   //reAdjustPreg(AOP(result));
10055
10056   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10057   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10058
10059
10060   tlbl = newiTempLabel(NULL);
10061   tlbl1= newiTempLabel(NULL);
10062
10063   size = AOP_SIZE(result);
10064   offset = 1;
10065
10066   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10067
10068   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10069
10070   /* offset should be 0, 1 or 3 */
10071   
10072   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10073   emitSKPNZ;
10074   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10075
10076   pic16_emitpcode(POC_MOVWF, pctemp);
10077
10078
10079   pic16_emitpLabel(tlbl->key);
10080
10081   emitCLRC;
10082   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
10083   while(--size)
10084     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10085
10086   pic16_emitpcode(POC_DECFSZ,  pctemp);
10087   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10088   pic16_emitpLabel(tlbl1->key);
10089
10090   pic16_popReleaseTempReg(pctemp,1);
10091
10092
10093  release:
10094   pic16_freeAsmop (right,NULL,ic,TRUE);
10095   pic16_freeAsmop(left,NULL,ic,TRUE);
10096   pic16_freeAsmop(result,NULL,ic,TRUE);
10097 }
10098 #endif
10099
10100 /*-----------------------------------------------------------------*/
10101 /* genrshOne - right shift a one byte quantity by known count      */
10102 /*-----------------------------------------------------------------*/
10103 static void genrshOne (operand *result, operand *left,
10104                        int shCount, int sign)
10105 {
10106     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10107     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10108 }
10109
10110 /*-----------------------------------------------------------------*/
10111 /* genrshTwo - right shift two bytes by known amount != 0          */
10112 /*-----------------------------------------------------------------*/
10113 static void genrshTwo (operand *result,operand *left,
10114                        int shCount, int sign)
10115 {
10116   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10117   /* if shCount >= 8 */
10118   if (shCount >= 8) {
10119     shCount -= 8 ;
10120     if (shCount)
10121       shiftR1Left2Result(left, MSB16, result, LSB,
10122                          shCount, sign);
10123     else
10124       movLeft2Result(left, MSB16, result, LSB);
10125
10126     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
10127
10128     if(sign) {
10129       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10130       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
10131     }
10132   }
10133
10134   /*  1 <= shCount <= 7 */
10135   else
10136     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
10137 }
10138
10139 /*-----------------------------------------------------------------*/
10140 /* shiftRLong - shift right one long from left to result           */
10141 /* offl = LSB or MSB16                                             */
10142 /*-----------------------------------------------------------------*/
10143 static void shiftRLong (operand *left, int offl,
10144                         operand *result, int sign)
10145 {
10146     int size = AOP_SIZE(result);
10147     int same = pic16_sameRegs(AOP(left),AOP(result));
10148     int i;
10149     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10150
10151         if (same && (offl == MSB16)) { //shift one byte right
10152                 for(i=MSB16;i<size;i++) {
10153                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10154                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10155                 }
10156         }
10157
10158     if(sign)
10159                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10160         else
10161                 emitCLRC;
10162
10163         if (same) {
10164                 if (offl == LSB)
10165                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10166         } else {
10167         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10168         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10169         }
10170
10171     if(offl == MSB16) {
10172         /* add sign of "a" */
10173         pic16_addSign(result, MSB32, sign);
10174         }
10175
10176         if (same) {
10177         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10178         } else {
10179         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10180         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10181         }
10182         
10183         if (same) {
10184         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10185         } else {
10186         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10187         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10188         }
10189
10190         if (same) {
10191         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10192         } else {
10193         if(offl == LSB){
10194                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10195                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10196         }
10197         }
10198 }
10199
10200 /*-----------------------------------------------------------------*/
10201 /* genrshFour - shift four byte by a known amount != 0             */
10202 /*-----------------------------------------------------------------*/
10203 static void genrshFour (operand *result, operand *left,
10204                         int shCount, int sign)
10205 {
10206   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10207   /* if shifting more that 3 bytes */
10208   if(shCount >= 24 ) {
10209     shCount -= 24;
10210     if(shCount)
10211       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10212     else
10213       movLeft2Result(left, MSB32, result, LSB);
10214
10215     pic16_addSign(result, MSB16, sign);
10216   }
10217   else if(shCount >= 16){
10218     shCount -= 16;
10219     if(shCount)
10220       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10221     else{
10222       movLeft2Result(left, MSB24, result, LSB);
10223       movLeft2Result(left, MSB32, result, MSB16);
10224     }
10225     pic16_addSign(result, MSB24, sign);
10226   }
10227   else if(shCount >= 8){
10228     shCount -= 8;
10229     if(shCount == 1)
10230       shiftRLong(left, MSB16, result, sign);
10231     else if(shCount == 0){
10232       movLeft2Result(left, MSB16, result, LSB);
10233       movLeft2Result(left, MSB24, result, MSB16);
10234       movLeft2Result(left, MSB32, result, MSB24);
10235       pic16_addSign(result, MSB32, sign);
10236     }
10237     else{ //shcount >= 2
10238       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10239       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10240       /* the last shift is signed */
10241       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10242       pic16_addSign(result, MSB32, sign);
10243     }
10244   }
10245   else{   /* 1 <= shCount <= 7 */
10246     if(shCount <= 2){
10247       shiftRLong(left, LSB, result, sign);
10248       if(shCount == 2)
10249         shiftRLong(result, LSB, result, sign);
10250     }
10251     else{
10252       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10253       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10254       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10255     }
10256   }
10257 }
10258
10259 /*-----------------------------------------------------------------*/
10260 /* genRightShiftLiteral - right shifting by known count            */
10261 /*-----------------------------------------------------------------*/
10262 static void genRightShiftLiteral (operand *left,
10263                                   operand *right,
10264                                   operand *result,
10265                                   iCode *ic,
10266                                   int sign)
10267 {    
10268   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10269   int lsize,res_size;
10270
10271   pic16_freeAsmop(right,NULL,ic,TRUE);
10272
10273   pic16_aopOp(left,ic,FALSE);
10274   pic16_aopOp(result,ic,FALSE);
10275
10276   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10277
10278 #if VIEW_SIZE
10279   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10280                  AOP_SIZE(left));
10281 #endif
10282
10283   lsize = pic16_getDataSize(left);
10284   res_size = pic16_getDataSize(result);
10285   /* test the LEFT size !!! */
10286
10287   /* I suppose that the left size >= result size */
10288   if(shCount == 0){
10289     while(res_size--)
10290       movLeft2Result(left, lsize, result, res_size);
10291   }
10292
10293   else if(shCount >= (lsize * 8)){
10294
10295     if(res_size == 1) {
10296       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10297       if(sign) {
10298         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10299         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10300       }
10301     } else {
10302
10303       if(sign) {
10304         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10305         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10306         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10307         while(res_size--)
10308           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10309
10310       } else {
10311
10312         while(res_size--)
10313           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10314       }
10315     }
10316   } else {
10317
10318     switch (res_size) {
10319     case 1:
10320       genrshOne (result,left,shCount,sign);
10321       break;
10322
10323     case 2:
10324       genrshTwo (result,left,shCount,sign);
10325       break;
10326
10327     case 4:
10328       genrshFour (result,left,shCount,sign);
10329       break;
10330     default :
10331       break;
10332     }
10333
10334   }
10335
10336   pic16_freeAsmop(left,NULL,ic,TRUE);
10337   pic16_freeAsmop(result,NULL,ic,TRUE);
10338 }
10339
10340 #if !(USE_GENERIC_SIGNED_SHIFT)
10341 /*-----------------------------------------------------------------*/
10342 /* genSignedRightShift - right shift of signed number              */
10343 /*-----------------------------------------------------------------*/
10344 static void genSignedRightShift (iCode *ic)
10345 {
10346   operand *right, *left, *result;
10347   int size, offset;
10348   //  char *l;
10349   symbol *tlbl, *tlbl1 ;
10350   pCodeOp *pctemp;
10351
10352   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10353
10354   /* we do it the hard way put the shift count in b
10355      and loop thru preserving the sign */
10356   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10357
10358   right = IC_RIGHT(ic);
10359   left  = IC_LEFT(ic);
10360   result = IC_RESULT(ic);
10361
10362   pic16_aopOp(right,ic,FALSE);  
10363   pic16_aopOp(left,ic,FALSE);
10364   pic16_aopOp(result,ic,FALSE);
10365
10366
10367   if ( AOP_TYPE(right) == AOP_LIT) {
10368     genRightShiftLiteral (left,right,result,ic,1);
10369     return ;
10370   }
10371   /* shift count is unknown then we have to form 
10372      a loop get the loop count in B : Note: we take
10373      only the lower order byte since shifting
10374      more that 32 bits make no sense anyway, ( the
10375      largest size of an object can be only 32 bits ) */  
10376
10377   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10378   //pic16_emitcode("inc","b");
10379   //pic16_freeAsmop (right,NULL,ic,TRUE);
10380   //pic16_aopOp(left,ic,FALSE);
10381   //pic16_aopOp(result,ic,FALSE);
10382
10383   /* now move the left to the result if they are not the
10384      same */
10385   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10386       AOP_SIZE(result) > 1) {
10387
10388     size = AOP_SIZE(result);
10389     offset=0;
10390     while (size--) { 
10391       /*
10392         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10393         if (*l == '@' && IS_AOP_PREG(result)) {
10394
10395         pic16_emitcode("mov","a,%s",l);
10396         pic16_aopPut(AOP(result),"a",offset);
10397         } else
10398         pic16_aopPut(AOP(result),l,offset);
10399       */
10400       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10401       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10402
10403       offset++;
10404     }
10405   }
10406
10407   /* mov the highest order bit to OVR */    
10408   tlbl = newiTempLabel(NULL);
10409   tlbl1= newiTempLabel(NULL);
10410
10411   size = AOP_SIZE(result);
10412   offset = size - 1;
10413
10414   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10415
10416   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10417
10418   /* offset should be 0, 1 or 3 */
10419   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10420   emitSKPNZ;
10421   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10422
10423   pic16_emitpcode(POC_MOVWF, pctemp);
10424
10425
10426   pic16_emitpLabel(tlbl->key);
10427
10428   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10429   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10430
10431   while(--size) {
10432     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10433   }
10434
10435   pic16_emitpcode(POC_DECFSZ,  pctemp);
10436   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10437   pic16_emitpLabel(tlbl1->key);
10438
10439   pic16_popReleaseTempReg(pctemp,1);
10440 #if 0
10441   size = AOP_SIZE(result);
10442   offset = size - 1;
10443   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10444   pic16_emitcode("rlc","a");
10445   pic16_emitcode("mov","ov,c");
10446   /* if it is only one byte then */
10447   if (size == 1) {
10448     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10449     MOVA(l);
10450     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10451     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10452     pic16_emitcode("mov","c,ov");
10453     pic16_emitcode("rrc","a");
10454     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10455     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10456     pic16_aopPut(AOP(result),"a",0);
10457     goto release ;
10458   }
10459
10460   reAdjustPreg(AOP(result));
10461   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10462   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10463   pic16_emitcode("mov","c,ov");
10464   while (size--) {
10465     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10466     MOVA(l);
10467     pic16_emitcode("rrc","a");         
10468     pic16_aopPut(AOP(result),"a",offset--);
10469   }
10470   reAdjustPreg(AOP(result));
10471   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10472   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10473
10474  release:
10475 #endif
10476
10477   pic16_freeAsmop(left,NULL,ic,TRUE);
10478   pic16_freeAsmop(result,NULL,ic,TRUE);
10479   pic16_freeAsmop(right,NULL,ic,TRUE);
10480 }
10481 #endif
10482
10483 #if !(USE_GENERIC_SIGNED_SHIFT)
10484 #warning This implementation of genRightShift() is incomplete!
10485 /*-----------------------------------------------------------------*/
10486 /* genRightShift - generate code for right shifting                */
10487 /*-----------------------------------------------------------------*/
10488 static void genRightShift (iCode *ic)
10489 {
10490     operand *right, *left, *result;
10491     sym_link *letype ;
10492     int size, offset;
10493     char *l;
10494     symbol *tlbl, *tlbl1 ;
10495
10496     /* if signed then we do it the hard way preserve the
10497     sign bit moving it inwards */
10498     letype = getSpec(operandType(IC_LEFT(ic)));
10499     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10500
10501     if (!SPEC_USIGN(letype)) {
10502         genSignedRightShift (ic);
10503         return ;
10504     }
10505
10506     /* signed & unsigned types are treated the same : i.e. the
10507     signed is NOT propagated inwards : quoting from the
10508     ANSI - standard : "for E1 >> E2, is equivalent to division
10509     by 2**E2 if unsigned or if it has a non-negative value,
10510     otherwise the result is implementation defined ", MY definition
10511     is that the sign does not get propagated */
10512
10513     right = IC_RIGHT(ic);
10514     left  = IC_LEFT(ic);
10515     result = IC_RESULT(ic);
10516
10517     pic16_aopOp(right,ic,FALSE);
10518
10519     /* if the shift count is known then do it 
10520     as efficiently as possible */
10521     if (AOP_TYPE(right) == AOP_LIT) {
10522         genRightShiftLiteral (left,right,result,ic, 0);
10523         return ;
10524     }
10525
10526     /* shift count is unknown then we have to form 
10527     a loop get the loop count in B : Note: we take
10528     only the lower order byte since shifting
10529     more that 32 bits make no sense anyway, ( the
10530     largest size of an object can be only 32 bits ) */  
10531
10532     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10533     pic16_emitcode("inc","b");
10534     pic16_aopOp(left,ic,FALSE);
10535     pic16_aopOp(result,ic,FALSE);
10536
10537     /* now move the left to the result if they are not the
10538     same */
10539     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10540         AOP_SIZE(result) > 1) {
10541
10542         size = AOP_SIZE(result);
10543         offset=0;
10544         while (size--) {
10545             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10546             if (*l == '@' && IS_AOP_PREG(result)) {
10547
10548                 pic16_emitcode("mov","a,%s",l);
10549                 pic16_aopPut(AOP(result),"a",offset);
10550             } else
10551                 pic16_aopPut(AOP(result),l,offset);
10552             offset++;
10553         }
10554     }
10555
10556     tlbl = newiTempLabel(NULL);
10557     tlbl1= newiTempLabel(NULL);
10558     size = AOP_SIZE(result);
10559     offset = size - 1;
10560
10561     /* if it is only one byte then */
10562     if (size == 1) {
10563
10564       tlbl = newiTempLabel(NULL);
10565       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10566         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10567         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10568       }
10569
10570       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10571       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10572       pic16_emitpLabel(tlbl->key);
10573       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10574       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10575       emitSKPC;
10576       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10577
10578       goto release ;
10579     }
10580
10581     reAdjustPreg(AOP(result));
10582     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10583     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10584     CLRC;
10585     while (size--) {
10586         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10587         MOVA(l);
10588         pic16_emitcode("rrc","a");         
10589         pic16_aopPut(AOP(result),"a",offset--);
10590     }
10591     reAdjustPreg(AOP(result));
10592
10593     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10594     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10595
10596 release:
10597     pic16_freeAsmop(left,NULL,ic,TRUE);
10598     pic16_freeAsmop (right,NULL,ic,TRUE);
10599     pic16_freeAsmop(result,NULL,ic,TRUE);
10600 }
10601 #endif
10602
10603 #if (USE_GENERIC_SIGNED_SHIFT)
10604 /*-----------------------------------------------------------------*/
10605 /* genGenericShift - generates code for left or right shifting     */
10606 /*-----------------------------------------------------------------*/
10607 static void genGenericShift (iCode *ic, int isShiftLeft) {
10608   operand *left,*right, *result;
10609   int offset;
10610   int sign, signedCount;
10611   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10612   PIC_OPCODE pos_shift, neg_shift;
10613
10614   FENTRY;
10615
10616   right = IC_RIGHT(ic);
10617   left  = IC_LEFT(ic);
10618   result = IC_RESULT(ic);
10619
10620   pic16_aopOp(right,ic,FALSE);
10621   pic16_aopOp(left,ic,FALSE);
10622   pic16_aopOp(result,ic,FALSE);
10623
10624   sign = !SPEC_USIGN(operandType (left));
10625   signedCount = !SPEC_USIGN(operandType (right));
10626
10627   /* if the shift count is known then do it 
10628      as efficiently as possible */
10629   if (AOP_TYPE(right) == AOP_LIT) {
10630     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10631     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10632     // we should modify right->aopu.aop_lit here!
10633     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10634     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10635     if (isShiftLeft)
10636       pic16_genLeftShiftLiteral (left,right,result,ic);
10637     else
10638       genRightShiftLiteral (left,right,result,ic, sign);
10639
10640     goto release;
10641   } // if (right is literal)
10642
10643   /* shift count is unknown then we have to form a loop.
10644    * Note: we take only the lower order byte since shifting
10645    * more than 32 bits make no sense anyway, ( the
10646    * largest size of an object can be only 32 bits )
10647    * Note: we perform arithmetic shifts if the left operand is
10648    * signed and we do an (effective) right shift, i. e. we
10649    * shift in the sign bit from the left. */
10650    
10651   label_complete = newiTempLabel ( NULL );
10652   label_loop_pos = newiTempLabel ( NULL );
10653   label_loop_neg = NULL;
10654   label_negative = NULL;
10655   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10656   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10657
10658   if (signedCount) {
10659     // additional labels needed
10660     label_loop_neg = newiTempLabel ( NULL );
10661     label_negative = newiTempLabel ( NULL );
10662   } // if
10663
10664   // copy source to result -- this will effectively truncate the left operand to the size of result!
10665   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10666   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10667   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10668     mov2f (AOP(result),AOP(left), offset);
10669   } // for
10670
10671   // if result is longer than left, fill with zeros (or sign)
10672   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10673     if (sign && AOP_SIZE(left) > 0) {
10674       // shift signed operand -- fill with sign
10675       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10676       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10677       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10678       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10679         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10680       } // for
10681     } else {
10682       // shift unsigned operand -- fill result with zeros
10683       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10684         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10685       } // for
10686     }
10687   } // if (size mismatch)
10688
10689   pic16_mov2w (AOP(right), 0);
10690   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10691   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10692   
10693 #if 0
10694   // perform a shift by one (shift count is positive)
10695   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10696   // 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])
10697   pic16_emitpLabel (label_loop_pos->key);
10698   emitCLRC;
10699   if (sign && (pos_shift == POC_RRCF)) {
10700     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10701     emitSETC;
10702   } // if
10703   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10704   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10705   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10706 #else
10707   // perform a shift by one (shift count is positive)
10708   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10709   // 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])
10710   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10711   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10712   emitCLRC;
10713   pic16_emitpLabel (label_loop_pos->key);
10714   if (sign && (pos_shift == POC_RRCF)) {
10715     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10716     emitSETC;
10717   } // if
10718   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10719   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10720   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10721   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10722 #endif
10723
10724   if (signedCount) {
10725     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10726
10727     pic16_emitpLabel (label_negative->key);
10728     // perform a shift by -1 (shift count is negative)
10729     // 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)
10730     emitCLRC;
10731     pic16_emitpLabel (label_loop_neg->key);
10732     if (sign && (neg_shift == POC_RRCF)) {
10733       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10734       emitSETC;
10735     } // if
10736     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10737     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10738     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10739     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10740   } // if (signedCount)
10741
10742   pic16_emitpLabel (label_complete->key);
10743
10744 release:
10745   pic16_freeAsmop (right,NULL,ic,TRUE);
10746   pic16_freeAsmop(left,NULL,ic,TRUE);
10747   pic16_freeAsmop(result,NULL,ic,TRUE);
10748 }
10749
10750 static void genLeftShift (iCode *ic) {
10751   genGenericShift (ic, 1);
10752 }
10753
10754 static void genRightShift (iCode *ic) {
10755   genGenericShift (ic, 0);
10756 }
10757 #endif
10758
10759
10760 void pic16_loadFSR0(operand *op)
10761 {
10762         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10763 }
10764
10765 /*-----------------------------------------------------------------*/
10766 /* genUnpackBits - generates code for unpacking bits               */
10767 /*-----------------------------------------------------------------*/
10768 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10769 {    
10770   int shCnt ;
10771   int rlen = 0 ;
10772   sym_link *etype, *letype;
10773   int blen=0, bstr=0;
10774   int lbstr;
10775   int offset = 0 ;
10776
10777     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10778     etype = getSpec(operandType(result));
10779     letype = getSpec(operandType(left));
10780     
10781 //    if(IS_BITFIELD(etype)) {
10782       blen = SPEC_BLEN(etype);
10783       bstr = SPEC_BSTR(etype);
10784 //    }
10785
10786     lbstr = SPEC_BSTR( letype );
10787
10788 #if 1
10789     if((blen == 1) && (bstr < 8)) {
10790       /* it is a single bit, so use the appropriate bit instructions */
10791       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10792
10793       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10794       
10795       if((ptype == POINTER) && (result)) {
10796         /* workaround to reduce the extra lfsr instruction */
10797         pic16_emitpcode(POC_BTFSC,
10798               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10799       } else {
10800         pic16_emitpcode(POC_BTFSC,
10801               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10802       }
10803         
10804       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10805
10806       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10807       return;
10808     }
10809
10810 #endif
10811
10812         /* the following call to pic16_loadFSR0 is temporary until
10813          * optimization to handle single bit assignments is added
10814          * to the function. Until then use the old safe way! -- VR */
10815         pic16_loadFSR0( left );
10816  
10817         /* read the first byte  */
10818         switch (ptype) {
10819                 case POINTER:
10820                 case IPOINTER:
10821                 case PPOINTER:
10822                 case FPOINTER:
10823                 case GPOINTER:
10824                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10825                         break;
10826                 case CPOINTER:
10827                         pic16_emitcode("clr","a");
10828                         pic16_emitcode("movc","a","@a+dptr");
10829                         break;
10830         }
10831         
10832
10833         /* if we have bitdisplacement then it fits   */
10834         /* into this byte completely or if length is */
10835         /* less than a byte                          */
10836         if ((shCnt = SPEC_BSTR(etype)) || 
10837                 (SPEC_BLEN(etype) <= 8))  {
10838
10839                 /* shift right acc */
10840                 AccRsh(shCnt, 0);
10841
10842                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10843                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10844
10845 /* VR -- normally I would use the following, but since we use the hack,
10846  * to avoid the masking from AccRsh, why not mask it right now? */
10847
10848 /*
10849                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10850 */
10851
10852                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10853           return ;
10854         }
10855
10856
10857
10858         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10859         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10860         exit(-1);
10861
10862     /* bit field did not fit in a byte  */
10863     rlen = SPEC_BLEN(etype) - 8;
10864     pic16_aopPut(AOP(result),"a",offset++);
10865
10866     while (1)  {
10867
10868         switch (ptype) {
10869         case POINTER:
10870         case IPOINTER:
10871             pic16_emitcode("inc","%s",rname);
10872             pic16_emitcode("mov","a,@%s",rname);
10873             break;
10874             
10875         case PPOINTER:
10876             pic16_emitcode("inc","%s",rname);
10877             pic16_emitcode("movx","a,@%s",rname);
10878             break;
10879
10880         case FPOINTER:
10881             pic16_emitcode("inc","dptr");
10882             pic16_emitcode("movx","a,@dptr");
10883             break;
10884             
10885         case CPOINTER:
10886             pic16_emitcode("clr","a");
10887             pic16_emitcode("inc","dptr");
10888             pic16_emitcode("movc","a","@a+dptr");
10889             break;
10890             
10891         case GPOINTER:
10892             pic16_emitcode("inc","dptr");
10893             pic16_emitcode("lcall","__gptrget");
10894             break;
10895         }
10896
10897         rlen -= 8;            
10898         /* if we are done */
10899         if ( rlen <= 0 )
10900             break ;
10901         
10902         pic16_aopPut(AOP(result),"a",offset++);
10903                               
10904     }
10905     
10906     if (rlen) {
10907         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10908         pic16_aopPut(AOP(result),"a",offset);          
10909     }
10910     
10911     return ;
10912 }
10913
10914
10915 static void genDataPointerGet(operand *left,
10916                               operand *result,
10917                               iCode *ic)
10918 {
10919   int size, offset = 0, leoffset=0 ;
10920
10921         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10922         pic16_aopOp(result, ic, FALSE);
10923
10924         size = AOP_SIZE(result);
10925 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10926
10927
10928 #if 0
10929         /* The following tests may save a redudant movff instruction when
10930          * accessing unions */
10931          
10932         /* if they are the same */
10933         if (operandsEqu (left, result)) {
10934                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10935                 goto release;
10936         }
10937 #endif
10938
10939 #if 0
10940         /* if they are the same registers */
10941         if (pic16_sameRegs(AOP(left),AOP(result))) {
10942                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10943                 goto release;
10944         }
10945 #endif
10946
10947 #if 1
10948         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10949                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10950                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10951                 goto release;
10952         }
10953 #endif
10954
10955
10956 #if 0
10957         if ( AOP_TYPE(left) == AOP_PCODE) {
10958                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
10959                                 AOP(left)->aopu.pcop->name,
10960                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
10961                                 PCOR(AOP(left)->aopu.pcop)->instance:
10962                                 PCOI(AOP(left)->aopu.pcop)->offset);
10963         }
10964 #endif
10965
10966         if(AOP(left)->aopu.pcop->type == PO_DIR)
10967                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10968
10969         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10970
10971         while (size--) {
10972                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10973                 
10974                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
10975                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
10976                         pic16_mov2w(AOP(left), offset); // patch 8
10977                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10978                 } else {
10979                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10980                                 pic16_popGet(AOP(left), offset), //patch 8
10981                                 pic16_popGet(AOP(result), offset)));
10982                 }
10983
10984                 offset++;
10985                 leoffset++;
10986         }
10987
10988 release:
10989     pic16_freeAsmop(result,NULL,ic,TRUE);
10990 }
10991
10992
10993
10994 /*-----------------------------------------------------------------*/
10995 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10996 /*-----------------------------------------------------------------*/
10997 static void genNearPointerGet (operand *left, 
10998                                operand *result, 
10999                                iCode *ic)
11000 {
11001   asmop *aop = NULL;
11002   //regs *preg = NULL ;
11003   sym_link *rtype, *retype;
11004   sym_link *ltype = operandType(left);    
11005
11006     FENTRY;
11007     
11008     rtype = operandType(result);
11009     retype= getSpec(rtype);
11010     
11011     pic16_aopOp(left,ic,FALSE);
11012
11013 //    pic16_DumpOp("(left)",left);
11014 //    pic16_DumpOp("(result)",result);
11015
11016     /* if left is rematerialisable and
11017      * result is not bit variable type and
11018      * the left is pointer to data space i.e
11019      * lower 128 bytes of space */
11020     
11021     if (AOP_TYPE(left) == AOP_PCODE
11022       && !IS_BITFIELD(retype)
11023       && DCL_TYPE(ltype) == POINTER) {
11024
11025         genDataPointerGet (left,result,ic);
11026         pic16_freeAsmop(left, NULL, ic, TRUE);
11027         return ;
11028     }
11029     
11030     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11031     pic16_aopOp (result,ic,FALSE);
11032     
11033     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11034
11035 #if 1
11036     if(IS_BITFIELD( retype )
11037       && (SPEC_BLEN(operandType(result))==1)
11038     ) {
11039       iCode *nextic;
11040       pCodeOp *jop;
11041       int bitstrt, bytestrt;
11042
11043         /* if this is bitfield of size 1, see if we are checking the value
11044          * of a single bit in an if-statement,
11045          * if yes, then don't generate usual code, but execute the
11046          * genIfx directly -- VR */
11047
11048         nextic = ic->next;
11049
11050         /* CHECK: if next iCode is IFX
11051          * and current result operand is nextic's conditional operand
11052          * and current result operand live ranges ends at nextic's key number
11053          */
11054         if((nextic->op == IFX)
11055           && (result == IC_COND(nextic))
11056           && (OP_LIVETO(result) == nextic->seq)
11057           ) {
11058             /* everything is ok then */
11059             /* find a way to optimize the genIfx iCode */
11060
11061             bytestrt = SPEC_BSTR(operandType(result))/8;
11062             bitstrt = SPEC_BSTR(operandType(result))%8;
11063             
11064             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11065
11066             genIfxpCOpJump(nextic, jop);
11067             
11068             pic16_freeAsmop(left, NULL, ic, TRUE);
11069             pic16_freeAsmop(result, NULL, ic, TRUE);
11070             return;
11071         }
11072     }
11073 #endif
11074
11075
11076     /* if the value is already in a pointer register
11077      * then don't need anything more */
11078     if (1 || !AOP_INPREG(AOP(left))) {  // AOP_INPREG(AOP(left)) is not always correct...
11079       /* otherwise get a free pointer register */
11080       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11081                 
11082       /* VR -- the whole concept is to load FSR0 with the address of the symbol */
11083       /* bitfields will be handled by genUnpackBits */
11084       if(!IS_BITFIELD(retype)) {
11085
11086         if(is_LitAOp( AOP(left) )) {
11087           pic16_loadFSR0( left );
11088         } else {
11089             // set up FSR0 with address from left
11090             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11091             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11092         }
11093       }
11094     }
11095
11096     /* if bitfield then unpack the bits */
11097     if (IS_BITFIELD(retype)) 
11098       genUnpackBits (result, left, NULL, POINTER);
11099     else {
11100       /* we have can just get the values */
11101       int size = AOP_SIZE(result);
11102       int offset = 0;   
11103         
11104       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11105
11106       /* fsr0 is loaded already -- VR */
11107 //      pic16_loadFSR0( left );
11108
11109 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
11110 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
11111       while(size--) {
11112         if(size) {
11113           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11114                 pic16_popGet(AOP(result), offset++)));
11115         } else {
11116           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11117                 pic16_popGet(AOP(result), offset++)));
11118         }
11119       }
11120 #if 0
11121 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
11122 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
11123       if(size)
11124         pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
11125 #endif
11126 /*
11127         while (size--) {
11128             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
11129
11130                 pic16_emitcode("mov","a,@%s",rname);
11131                 pic16_aopPut(AOP(result),"a",offset);
11132             } else {
11133                 sprintf(buffer,"@%s",rname);
11134                 pic16_aopPut(AOP(result),buffer,offset);
11135             }
11136             offset++ ;
11137             if (size)
11138                 pic16_emitcode("inc","%s",rname);
11139         }
11140 */
11141     }
11142
11143     /* now some housekeeping stuff */
11144     if (aop) {
11145       /* we had to allocate for this iCode */
11146       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11147       pic16_freeAsmop(NULL,aop,ic,TRUE);
11148     } else { 
11149       /* we did not allocate which means left
11150        * already in a pointer register, then
11151        * if size > 0 && this could be used again
11152        * we have to point it back to where it 
11153        * belongs */
11154       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11155       if (AOP_SIZE(result) > 1
11156         && !OP_SYMBOL(left)->remat
11157         && ( OP_SYMBOL(left)->liveTo > ic->seq
11158             || ic->depth )) {
11159 //        int size = AOP_SIZE(result) - 1;
11160 //        while (size--)
11161 //          pic16_emitcode("dec","%s",rname);
11162         }
11163     }
11164
11165     /* done */
11166     pic16_freeAsmop(left,NULL,ic,TRUE);
11167     pic16_freeAsmop(result,NULL,ic,TRUE);
11168 }
11169
11170 /*-----------------------------------------------------------------*/
11171 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
11172 /*-----------------------------------------------------------------*/
11173 static void genPagedPointerGet (operand *left, 
11174                                operand *result, 
11175                                iCode *ic)
11176 {
11177     asmop *aop = NULL;
11178     regs *preg = NULL ;
11179     char *rname ;
11180     sym_link *rtype, *retype;    
11181
11182     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11183
11184     rtype = operandType(result);
11185     retype= getSpec(rtype);
11186     
11187     pic16_aopOp(left,ic,FALSE);
11188
11189   /* if the value is already in a pointer register
11190        then don't need anything more */
11191     if (!AOP_INPREG(AOP(left))) {
11192         /* otherwise get a free pointer register */
11193         aop = newAsmop(0);
11194         preg = getFreePtr(ic,&aop,FALSE);
11195         pic16_emitcode("mov","%s,%s",
11196                 preg->name,
11197                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11198         rname = preg->name ;
11199     } else
11200         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11201     
11202     pic16_freeAsmop(left,NULL,ic,TRUE);
11203     pic16_aopOp (result,ic,FALSE);
11204
11205     /* if bitfield then unpack the bits */
11206     if (IS_BITFIELD(retype)) 
11207         genUnpackBits (result,left,rname,PPOINTER);
11208     else {
11209         /* we have can just get the values */
11210         int size = AOP_SIZE(result);
11211         int offset = 0 ;        
11212         
11213         while (size--) {
11214             
11215             pic16_emitcode("movx","a,@%s",rname);
11216             pic16_aopPut(AOP(result),"a",offset);
11217             
11218             offset++ ;
11219             
11220             if (size)
11221                 pic16_emitcode("inc","%s",rname);
11222         }
11223     }
11224
11225     /* now some housekeeping stuff */
11226     if (aop) {
11227         /* we had to allocate for this iCode */
11228         pic16_freeAsmop(NULL,aop,ic,TRUE);
11229     } else { 
11230         /* we did not allocate which means left
11231            already in a pointer register, then
11232            if size > 0 && this could be used again
11233            we have to point it back to where it 
11234            belongs */
11235         if (AOP_SIZE(result) > 1 &&
11236             !OP_SYMBOL(left)->remat &&
11237             ( OP_SYMBOL(left)->liveTo > ic->seq ||
11238               ic->depth )) {
11239             int size = AOP_SIZE(result) - 1;
11240             while (size--)
11241                 pic16_emitcode("dec","%s",rname);
11242         }
11243     }
11244
11245     /* done */
11246     pic16_freeAsmop(result,NULL,ic,TRUE);
11247     
11248         
11249 }
11250
11251 /*-----------------------------------------------------------------*/
11252 /* genFarPointerGet - gget value from far space                    */
11253 /*-----------------------------------------------------------------*/
11254 static void genFarPointerGet (operand *left,
11255                               operand *result, iCode *ic)
11256 {
11257     int size, offset ;
11258     sym_link *retype = getSpec(operandType(result));
11259
11260     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11261
11262     pic16_aopOp(left,ic,FALSE);
11263
11264     /* if the operand is already in dptr 
11265     then we do nothing else we move the value to dptr */
11266     if (AOP_TYPE(left) != AOP_STR) {
11267         /* if this is remateriazable */
11268         if (AOP_TYPE(left) == AOP_IMMD)
11269             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11270         else { /* we need to get it byte by byte */
11271             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11272             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11273             if (options.model == MODEL_FLAT24)
11274             {
11275                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11276             }
11277         }
11278     }
11279     /* so dptr know contains the address */
11280     pic16_freeAsmop(left,NULL,ic,TRUE);
11281     pic16_aopOp(result,ic,FALSE);
11282
11283     /* if bit then unpack */
11284     if (IS_BITFIELD(retype)) 
11285         genUnpackBits(result,left,"dptr",FPOINTER);
11286     else {
11287         size = AOP_SIZE(result);
11288         offset = 0 ;
11289
11290         while (size--) {
11291             pic16_emitcode("movx","a,@dptr");
11292             pic16_aopPut(AOP(result),"a",offset++);
11293             if (size)
11294                 pic16_emitcode("inc","dptr");
11295         }
11296     }
11297
11298     pic16_freeAsmop(result,NULL,ic,TRUE);
11299 }
11300
11301 #if 0
11302 /*-----------------------------------------------------------------*/
11303 /* genCodePointerGet - get value from code space                  */
11304 /*-----------------------------------------------------------------*/
11305 static void genCodePointerGet (operand *left,
11306                                 operand *result, iCode *ic)
11307 {
11308     int size, offset ;
11309     sym_link *retype = getSpec(operandType(result));
11310
11311     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11312
11313     pic16_aopOp(left,ic,FALSE);
11314
11315     /* if the operand is already in dptr 
11316     then we do nothing else we move the value to dptr */
11317     if (AOP_TYPE(left) != AOP_STR) {
11318         /* if this is remateriazable */
11319         if (AOP_TYPE(left) == AOP_IMMD)
11320             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11321         else { /* we need to get it byte by byte */
11322             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11323             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11324             if (options.model == MODEL_FLAT24)
11325             {
11326                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11327             }
11328         }
11329     }
11330     /* so dptr know contains the address */
11331     pic16_freeAsmop(left,NULL,ic,TRUE);
11332     pic16_aopOp(result,ic,FALSE);
11333
11334     /* if bit then unpack */
11335     if (IS_BITFIELD(retype)) 
11336         genUnpackBits(result,left,"dptr",CPOINTER);
11337     else {
11338         size = AOP_SIZE(result);
11339         offset = 0 ;
11340
11341         while (size--) {
11342             pic16_emitcode("clr","a");
11343             pic16_emitcode("movc","a,@a+dptr");
11344             pic16_aopPut(AOP(result),"a",offset++);
11345             if (size)
11346                 pic16_emitcode("inc","dptr");
11347         }
11348     }
11349
11350     pic16_freeAsmop(result,NULL,ic,TRUE);
11351 }
11352 #endif
11353
11354 #if 0
11355 /*-----------------------------------------------------------------*/
11356 /* genGenPointerGet - gget value from generic pointer space        */
11357 /*-----------------------------------------------------------------*/
11358 static void genGenPointerGet (operand *left,
11359                               operand *result, iCode *ic)
11360 {
11361   int size, offset, lit;
11362   sym_link *retype = getSpec(operandType(result));
11363
11364         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11365         pic16_aopOp(left,ic,FALSE);
11366         pic16_aopOp(result,ic,FALSE);
11367         size = AOP_SIZE(result);
11368
11369         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11370
11371         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11372
11373                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11374                 // load FSR0 from immediate
11375                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11376
11377 //              pic16_loadFSR0( left );
11378
11379                 offset = 0;
11380                 while(size--) {
11381                         if(size) {
11382                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11383                         } else {
11384                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11385                         }
11386                         offset++;
11387                 }
11388                 goto release;
11389
11390         }
11391         else { /* we need to get it byte by byte */
11392                 // set up FSR0 with address from left
11393                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11394                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11395
11396                 offset = 0 ;
11397
11398                 while(size--) {
11399                         if(size) {
11400                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11401                         } else {
11402                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11403                         }
11404                         offset++;
11405                 }
11406                 goto release;
11407         }
11408
11409   /* if bit then unpack */
11410         if (IS_BITFIELD(retype)) 
11411                 genUnpackBits(result,left,"BAD",GPOINTER);
11412
11413         release:
11414         pic16_freeAsmop(left,NULL,ic,TRUE);
11415         pic16_freeAsmop(result,NULL,ic,TRUE);
11416
11417 }
11418 #endif
11419
11420
11421 /*-----------------------------------------------------------------*/
11422 /* genGenPointerGet - gget value from generic pointer space        */
11423 /*-----------------------------------------------------------------*/
11424 static void genGenPointerGet (operand *left,
11425                               operand *result, iCode *ic)
11426 {
11427   int size, offset, lit;
11428   sym_link *retype = getSpec(operandType(result));
11429   char fgptrget[32];
11430
11431     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11432     pic16_aopOp(left,ic,FALSE);
11433     pic16_aopOp(result,ic,FALSE);
11434     size = AOP_SIZE(result);
11435
11436     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11437
11438     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11439
11440       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11441       // load FSR0 from immediate
11442       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11443
11444       werror(W_POSSBUG2, __FILE__, __LINE__);
11445
11446       offset = 0;
11447       while(size--) {
11448         if(size) {
11449           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11450         } else {
11451           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11452         }
11453         offset++;
11454       }
11455
11456       goto release;
11457
11458     } else { /* we need to get it byte by byte */
11459
11460       /* set up WREG:PRODL:FSR0L with address from left */
11461       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11462       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11463       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11464       
11465       switch( size ) {
11466         case 1: strcpy(fgptrget, "__gptrget1"); break;
11467         case 2: strcpy(fgptrget, "__gptrget2"); break;
11468         case 3: strcpy(fgptrget, "__gptrget3"); break;
11469         case 4: strcpy(fgptrget, "__gptrget4"); break;
11470         default:
11471           werror(W_POSSBUG2, __FILE__, __LINE__);
11472           abort();
11473       }
11474       
11475       pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11476       
11477       assignResultValue(result, 1);
11478       
11479       {
11480         symbol *sym;
11481
11482           sym = newSymbol( fgptrget, 0 );
11483           strcpy(sym->rname, fgptrget);
11484           checkAddSym(&externs, sym);
11485
11486 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11487       }
11488               
11489       goto release;
11490     }
11491
11492   /* if bit then unpack */
11493     if (IS_BITFIELD(retype)) 
11494       genUnpackBits(result,left,"BAD",GPOINTER);
11495
11496 release:
11497   pic16_freeAsmop(left,NULL,ic,TRUE);
11498   pic16_freeAsmop(result,NULL,ic,TRUE);
11499 }
11500
11501 /*-----------------------------------------------------------------*/
11502 /* genConstPointerGet - get value from const generic pointer space */
11503 /*-----------------------------------------------------------------*/
11504 static void genConstPointerGet (operand *left,
11505                                 operand *result, iCode *ic)
11506 {
11507   //sym_link *retype = getSpec(operandType(result));
11508   // symbol *albl = newiTempLabel(NULL);        // patch 15
11509   // symbol *blbl = newiTempLabel(NULL);        //
11510   // PIC_OPCODE poc;                            // patch 15
11511   int size;
11512   int offset = 0;
11513
11514   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11515   pic16_aopOp(left,ic,FALSE);
11516   pic16_aopOp(result,ic,TRUE);
11517   size = AOP_SIZE(result);
11518
11519   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11520
11521   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11522
11523   // set up table pointer
11524   if( (AOP_TYPE(left) == AOP_PCODE) 
11525       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11526           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11527     {
11528       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11529       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11530       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11531       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11532       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11533       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11534   } else {
11535     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11536     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11537     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11538   }
11539
11540   while(size--) {
11541     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11542     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11543     offset++;
11544   }
11545     
11546   pic16_freeAsmop(left,NULL,ic,TRUE);
11547   pic16_freeAsmop(result,NULL,ic,TRUE);
11548 }
11549
11550
11551 /*-----------------------------------------------------------------*/
11552 /* genPointerGet - generate code for pointer get                   */
11553 /*-----------------------------------------------------------------*/
11554 static void genPointerGet (iCode *ic)
11555 {
11556   operand *left, *result ;
11557   sym_link *type, *etype;
11558   int p_type;
11559
11560     FENTRY;
11561     
11562     left = IC_LEFT(ic);
11563     result = IC_RESULT(ic) ;
11564
11565     /* depending on the type of pointer we need to
11566     move it to the correct pointer register */
11567     type = operandType(left);
11568     etype = getSpec(type);
11569
11570 #if 0
11571     if (IS_PTR_CONST(type))
11572 #else
11573     if (IS_CODEPTR(type))
11574 #endif
11575       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11576
11577     /* if left is of type of pointer then it is simple */
11578     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11579       p_type = DCL_TYPE(type);
11580     else {
11581       /* we have to go by the storage class */
11582       p_type = PTR_TYPE(SPEC_OCLS(etype));
11583
11584       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11585
11586       if (SPEC_OCLS(etype)->codesp ) {
11587         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11588         //p_type = CPOINTER ;   
11589       } else
11590       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11591         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11592         /*p_type = FPOINTER ;*/ 
11593       } else
11594       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11595         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11596         /* p_type = PPOINTER; */
11597       } else
11598       if (SPEC_OCLS(etype) == idata ) {
11599         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11600         /* p_type = IPOINTER; */
11601       } else {
11602         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11603         /* p_type = POINTER ; */
11604       }
11605     }
11606
11607     /* now that we have the pointer type we assign
11608     the pointer values */
11609     switch (p_type) {
11610       case POINTER:     
11611       case IPOINTER:
11612         genNearPointerGet (left,result,ic);
11613         break;
11614
11615       case PPOINTER:
11616         genPagedPointerGet(left,result,ic);
11617         break;
11618
11619       case FPOINTER:
11620         genFarPointerGet (left,result,ic);
11621         break;
11622
11623       case CPOINTER:
11624         genConstPointerGet (left,result,ic);
11625         //pic16_emitcodePointerGet (left,result,ic);
11626         break;
11627
11628       case GPOINTER:
11629 #if 0
11630       if (IS_PTR_CONST(type))
11631         genConstPointerGet (left,result,ic);
11632       else
11633 #endif
11634         genGenPointerGet (left,result,ic);
11635       break;
11636
11637     default:
11638       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11639               "genPointerGet: illegal pointer type");
11640     
11641     }
11642 }
11643
11644 /*-----------------------------------------------------------------*/
11645 /* genPackBits - generates code for packed bit storage             */
11646 /*-----------------------------------------------------------------*/
11647 static void genPackBits (sym_link    *etype , operand *result,
11648                          operand *right ,
11649                          char *rname, int p_type)
11650 {
11651   int shCnt = 0 ;
11652   int offset = 0  ;
11653   int rLen = 0 ;
11654   int blen, bstr ;   
11655   sym_link *retype;
11656   char *l ;
11657
11658         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11659         blen = SPEC_BLEN(etype);
11660         bstr = SPEC_BSTR(etype);
11661
11662         retype = getSpec(operandType(right));
11663
11664         if(AOP_TYPE(right) == AOP_LIT) {
11665                 if((blen == 1) && (bstr < 8)) {
11666                   unsigned long lit;
11667                         /* it is a single bit, so use the appropriate bit instructions */
11668
11669                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11670
11671                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11672 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11673                         if((p_type == POINTER) && (result)) {
11674                                 /* workaround to reduce the extra lfsr instruction */
11675                                 if(lit) {
11676                                         pic16_emitpcode(POC_BSF,
11677                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11678                                 } else {
11679                                         pic16_emitpcode(POC_BCF,
11680                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11681                                 }
11682                         } else {
11683                                 pic16_loadFSR0( result );
11684                                 if(lit) {
11685                                         pic16_emitpcode(POC_BSF,
11686                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11687                                 } else {
11688                                         pic16_emitpcode(POC_BCF,
11689                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11690                                 }
11691                         }
11692         
11693                   return;
11694                 }
11695
11696                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11697                 offset++;
11698         } else
11699         if(IS_BITFIELD(retype) 
11700           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11701           && (blen == 1)) {
11702           int rblen, rbstr;
11703
11704             rblen = SPEC_BLEN( retype );
11705             rbstr = SPEC_BSTR( retype );
11706             
11707
11708             if(IS_BITFIELD(etype)) {
11709               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11710               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11711             } else {
11712               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11713             }
11714             
11715             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11716             
11717             if(IS_BITFIELD(etype)) {
11718               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11719             } else {
11720               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11721             }
11722
11723             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11724             
11725             return;
11726         } else
11727           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11728
11729         /* if the bit lenth is less than or    */
11730         /* it exactly fits a byte then         */
11731         if((shCnt=SPEC_BSTR(etype))
11732                 || SPEC_BLEN(etype) <= 8 )  {
11733
11734                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11735
11736                 /* shift left acc */
11737                 AccLsh(shCnt);
11738
11739                 /* using PRODL as a temporary register here */
11740                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11741
11742                 switch (p_type) {
11743                         case FPOINTER:
11744                         case POINTER:
11745                                 pic16_loadFSR0( result );
11746                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11747 //                              pic16_emitcode ("mov","b,a");
11748 //                              pic16_emitcode("mov","a,@%s",rname);
11749                                 break;
11750
11751                         case GPOINTER:
11752                                 werror(W_POSSBUG2, __FILE__, __LINE__);
11753                                 break;
11754
11755                 }
11756 #if 1
11757                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11758                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11759                                         (unsigned char)(0xff >> (8-bstr))) ));
11760                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
11761                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11762 #endif
11763
11764           return;
11765         }
11766
11767
11768         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11769         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11770         exit(-1);
11771
11772
11773     /* if we r done */
11774     if ( SPEC_BLEN(etype) <= 8 )
11775         return ;
11776
11777     pic16_emitcode("inc","%s",rname);
11778     rLen = SPEC_BLEN(etype) ;     
11779
11780
11781
11782     /* now generate for lengths greater than one byte */
11783     while (1) {
11784
11785         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
11786
11787         rLen -= 8 ;
11788         if (rLen <= 0 )
11789             break ;
11790
11791         switch (p_type) {
11792             case POINTER:
11793                 if (*l == '@') {
11794                     MOVA(l);
11795                     pic16_emitcode("mov","@%s,a",rname);
11796                 } else
11797                     pic16_emitcode("mov","@%s,%s",rname,l);
11798                 break;
11799
11800             case FPOINTER:
11801                 MOVA(l);
11802                 pic16_emitcode("movx","@dptr,a");
11803                 break;
11804
11805             case GPOINTER:
11806                 MOVA(l);
11807                 DEBUGpic16_emitcode(";lcall","__gptrput");
11808                 break;  
11809         }   
11810         pic16_emitcode ("inc","%s",rname);
11811     }
11812
11813     MOVA(l);
11814
11815     /* last last was not complete */
11816     if (rLen)   {
11817         /* save the byte & read byte */
11818         switch (p_type) {
11819             case POINTER:
11820                 pic16_emitcode ("mov","b,a");
11821                 pic16_emitcode("mov","a,@%s",rname);
11822                 break;
11823
11824             case FPOINTER:
11825                 pic16_emitcode ("mov","b,a");
11826                 pic16_emitcode("movx","a,@dptr");
11827                 break;
11828
11829             case GPOINTER:
11830                 pic16_emitcode ("push","b");
11831                 pic16_emitcode ("push","acc");
11832                 pic16_emitcode ("lcall","__gptrget");
11833                 pic16_emitcode ("pop","b");
11834                 break;
11835         }
11836
11837         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11838         pic16_emitcode ("orl","a,b");
11839     }
11840
11841     if (p_type == GPOINTER)
11842         pic16_emitcode("pop","b");
11843
11844     switch (p_type) {
11845
11846     case POINTER:
11847         pic16_emitcode("mov","@%s,a",rname);
11848         break;
11849         
11850     case FPOINTER:
11851         pic16_emitcode("movx","@dptr,a");
11852         break;
11853         
11854     case GPOINTER:
11855         DEBUGpic16_emitcode(";lcall","__gptrput");
11856         break;                  
11857     }
11858 }
11859 /*-----------------------------------------------------------------*/
11860 /* genDataPointerSet - remat pointer to data space                 */
11861 /*-----------------------------------------------------------------*/
11862 static void genDataPointerSet(operand *right,
11863                               operand *result,
11864                               iCode *ic)
11865 {
11866     int size, offset = 0, resoffset=0 ;
11867
11868     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11869     pic16_aopOp(right,ic,FALSE);
11870
11871     size = AOP_SIZE(right);
11872
11873 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11874
11875 #if 0
11876     if ( AOP_TYPE(result) == AOP_PCODE) {
11877       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11878               AOP(result)->aopu.pcop->name,
11879                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11880               PCOR(AOP(result)->aopu.pcop)->instance:
11881               PCOI(AOP(result)->aopu.pcop)->offset);
11882     }
11883 #endif
11884
11885         if(AOP(result)->aopu.pcop->type == PO_DIR)
11886                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11887
11888         while (size--) {
11889                 if (AOP_TYPE(right) == AOP_LIT) {
11890                   unsigned int lit;
11891
11892                     if(!IS_FLOAT(operandType( right )))
11893                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11894                     else {
11895                       union {
11896                         unsigned long lit_int;
11897                         float lit_float;
11898                       } info;
11899         
11900                         /* take care if literal is a float */
11901                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11902                         lit = info.lit_int;
11903                     }
11904
11905                     lit = lit >> (8*offset);
11906                     if(lit&0xff) {
11907                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11908                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11909                     } else {
11910                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11911                     }
11912                 } else {
11913                   pic16_mov2w(AOP(right), offset);
11914                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11915                 }
11916                 offset++;
11917                 resoffset++;
11918         }
11919
11920     pic16_freeAsmop(right,NULL,ic,TRUE);
11921 }
11922
11923
11924
11925 /*-----------------------------------------------------------------*/
11926 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11927 /*-----------------------------------------------------------------*/
11928 static void genNearPointerSet (operand *right,
11929                                operand *result, 
11930                                iCode *ic)
11931 {
11932   asmop *aop = NULL;
11933   char *l;
11934   sym_link *retype;
11935   sym_link *ptype = operandType(result);
11936   sym_link *resetype;
11937     
11938         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11939         retype= getSpec(operandType(right));
11940         resetype = getSpec(operandType(result));
11941   
11942         pic16_aopOp(result,ic,FALSE);
11943     
11944         /* if the result is rematerializable &
11945          * in data space & not a bit variable */
11946         
11947         /* and result is not a bit variable */
11948         if (AOP_TYPE(result) == AOP_PCODE
11949 //              && AOP_TYPE(result) == AOP_IMMD
11950                 && DCL_TYPE(ptype) == POINTER
11951                 && !IS_BITFIELD(retype)
11952                 && !IS_BITFIELD(resetype)) {
11953
11954                 genDataPointerSet (right,result,ic);
11955                 pic16_freeAsmop(result,NULL,ic,TRUE);
11956           return;
11957         }
11958
11959         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11960         pic16_aopOp(right,ic,FALSE);
11961         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11962
11963         /* if the value is already in a pointer register
11964          * then don't need anything more */
11965         if (1 || !AOP_INPREG(AOP(result))) {  // AOP_INPREG(AOP(result)) is not always correct...
11966                 /* otherwise get a free pointer register */
11967                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11968
11969 //              if( (AOP_TYPE(result) == AOP_PCODE) 
11970 //                      && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
11971 //                              || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
11972                 if(is_LitAOp( AOP(result) ))
11973                 {
11974                   if(!IS_BITFIELD(resetype))
11975                         pic16_loadFSR0( result );  // patch 10
11976                 } else {
11977                   if(!IS_BITFIELD(resetype)) {
11978                         // set up FSR0 with address of result
11979                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11980                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11981                   }
11982                 }
11983
11984         }
11985 //      else
11986 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11987
11988         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11989
11990 //      pic16_loadFSR0( result );
11991
11992         /* if bitfield then unpack the bits */
11993         if (IS_BITFIELD(resetype)) {
11994                 genPackBits (resetype, result, right, NULL, POINTER);
11995         } else {
11996                 /* we have can just get the values */
11997           int size = AOP_SIZE(right);
11998           int offset = 0 ;    
11999
12000                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12001                 while (size--) {
12002                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12003                         if (*l == '@' ) {
12004                                 //MOVA(l);
12005                                 //pic16_emitcode("mov","@%s,a",rname);
12006                                 pic16_emitcode("movf","indf0,w ;1");
12007                         } else {
12008
12009                                 if (AOP_TYPE(right) == AOP_LIT) {
12010                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12011                                         if (size) {
12012                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12013                                         } else {
12014                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12015                                         }
12016                                 } else { // no literal
12017                                         if(size) {
12018                                                 pic16_emitpcode(POC_MOVFF,
12019                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12020                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12021                                         } else {
12022                                                 pic16_emitpcode(POC_MOVFF,
12023                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12024                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12025                                         }
12026                                 }
12027                         }
12028                         offset++;
12029                 }
12030         }
12031
12032         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12033         /* now some housekeeping stuff */
12034         if (aop) {
12035                 /* we had to allocate for this iCode */
12036                 pic16_freeAsmop(NULL,aop,ic,TRUE);
12037         } else { 
12038                 /* we did not allocate which means left
12039                  * already in a pointer register, then
12040                  * if size > 0 && this could be used again
12041                  * we have to point it back to where it 
12042                  * belongs */
12043                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12044                 if (AOP_SIZE(right) > 1
12045                         && !OP_SYMBOL(result)->remat
12046                         && ( OP_SYMBOL(result)->liveTo > ic->seq
12047                                 || ic->depth )) {
12048
12049                   int size = AOP_SIZE(right) - 1;
12050
12051                         while (size--)
12052                                 pic16_emitcode("decf","fsr0,f");
12053                         //pic16_emitcode("dec","%s",rname);
12054                 }
12055         }
12056
12057         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12058         /* done */
12059 //release:
12060         pic16_freeAsmop(right,NULL,ic,TRUE);
12061         pic16_freeAsmop(result,NULL,ic,TRUE);
12062 }
12063
12064 /*-----------------------------------------------------------------*/
12065 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
12066 /*-----------------------------------------------------------------*/
12067 static void genPagedPointerSet (operand *right,
12068                                operand *result, 
12069                                iCode *ic)
12070 {
12071     asmop *aop = NULL;
12072     regs *preg = NULL ;
12073     char *rname , *l;
12074     sym_link *retype;
12075        
12076     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12077
12078     retype= getSpec(operandType(right));
12079     
12080     pic16_aopOp(result,ic,FALSE);
12081     
12082     /* if the value is already in a pointer register
12083        then don't need anything more */
12084     if (!AOP_INPREG(AOP(result))) {
12085         /* otherwise get a free pointer register */
12086         aop = newAsmop(0);
12087         preg = getFreePtr(ic,&aop,FALSE);
12088         pic16_emitcode("mov","%s,%s",
12089                 preg->name,
12090                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12091         rname = preg->name ;
12092     } else
12093         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12094     
12095     pic16_freeAsmop(result,NULL,ic,TRUE);
12096     pic16_aopOp (right,ic,FALSE);
12097
12098     /* if bitfield then unpack the bits */
12099     if (IS_BITFIELD(retype)) 
12100         genPackBits (retype,result,right,rname,PPOINTER);
12101     else {
12102         /* we have can just get the values */
12103         int size = AOP_SIZE(right);
12104         int offset = 0 ;        
12105         
12106         while (size--) {
12107             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12108             
12109             MOVA(l);
12110             pic16_emitcode("movx","@%s,a",rname);
12111
12112             if (size)
12113                 pic16_emitcode("inc","%s",rname);
12114
12115             offset++;
12116         }
12117     }
12118     
12119     /* now some housekeeping stuff */
12120     if (aop) {
12121         /* we had to allocate for this iCode */
12122         pic16_freeAsmop(NULL,aop,ic,TRUE);
12123     } else { 
12124         /* we did not allocate which means left
12125            already in a pointer register, then
12126            if size > 0 && this could be used again
12127            we have to point it back to where it 
12128            belongs */
12129         if (AOP_SIZE(right) > 1 &&
12130             !OP_SYMBOL(result)->remat &&
12131             ( OP_SYMBOL(result)->liveTo > ic->seq ||
12132               ic->depth )) {
12133             int size = AOP_SIZE(right) - 1;
12134             while (size--)
12135                 pic16_emitcode("dec","%s",rname);
12136         }
12137     }
12138
12139     /* done */
12140     pic16_freeAsmop(right,NULL,ic,TRUE);
12141     
12142         
12143 }
12144
12145 /*-----------------------------------------------------------------*/
12146 /* genFarPointerSet - set value from far space                     */
12147 /*-----------------------------------------------------------------*/
12148 static void genFarPointerSet (operand *right,
12149                               operand *result, iCode *ic)
12150 {
12151     int size, offset ;
12152     sym_link *retype = getSpec(operandType(right));
12153
12154     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12155     pic16_aopOp(result,ic,FALSE);
12156
12157     /* if the operand is already in dptr 
12158     then we do nothing else we move the value to dptr */
12159     if (AOP_TYPE(result) != AOP_STR) {
12160         /* if this is remateriazable */
12161         if (AOP_TYPE(result) == AOP_IMMD)
12162             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12163         else { /* we need to get it byte by byte */
12164             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12165             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12166             if (options.model == MODEL_FLAT24)
12167             {
12168                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12169             }
12170         }
12171     }
12172     /* so dptr know contains the address */
12173     pic16_freeAsmop(result,NULL,ic,TRUE);
12174     pic16_aopOp(right,ic,FALSE);
12175
12176     /* if bit then unpack */
12177     if (IS_BITFIELD(retype)) 
12178         genPackBits(retype,result,right,"dptr",FPOINTER);
12179     else {
12180         size = AOP_SIZE(right);
12181         offset = 0 ;
12182
12183         while (size--) {
12184             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12185             MOVA(l);
12186             pic16_emitcode("movx","@dptr,a");
12187             if (size)
12188                 pic16_emitcode("inc","dptr");
12189         }
12190     }
12191
12192     pic16_freeAsmop(right,NULL,ic,TRUE);
12193 }
12194
12195 /*-----------------------------------------------------------------*/
12196 /* genGenPointerSet - set value from generic pointer space         */
12197 /*-----------------------------------------------------------------*/
12198 #if 0
12199 static void genGenPointerSet (operand *right,
12200                               operand *result, iCode *ic)
12201 {
12202         int i, size, offset, lit;
12203         sym_link *retype = getSpec(operandType(right));
12204
12205         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12206
12207         pic16_aopOp(result,ic,FALSE);
12208         pic16_aopOp(right,ic,FALSE);
12209         size = AOP_SIZE(right);
12210         offset = 0;
12211
12212         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12213
12214         /* if the operand is already in dptr 
12215                 then we do nothing else we move the value to dptr */
12216         if (AOP_TYPE(result) != AOP_STR) {
12217                 /* if this is remateriazable */
12218                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12219                 // WARNING: anythig until "else" is untested!
12220                 if (AOP_TYPE(result) == AOP_IMMD) {
12221                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12222                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12223                         // load FSR0 from immediate
12224                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12225                         offset = 0;
12226                         while(size--) {
12227                                 if(size) {
12228                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12229                                 } else {
12230                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12231                                 }
12232                                 offset++;
12233                         }
12234                         goto release;
12235                 }
12236                 else { /* we need to get it byte by byte */
12237                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12238                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12239
12240                         // set up FSR0 with address of result
12241                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12242                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12243
12244                         /* hack hack! see if this the FSR. If so don't load W */
12245                         if(AOP_TYPE(right) != AOP_ACC) {
12246
12247                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12248
12249                                 if(AOP_TYPE(right) == AOP_LIT)
12250                                 {
12251                                         // copy literal
12252                                         // note: pic16_popGet handles sign extension
12253                                         for(i=0;i<size;i++) {
12254                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12255                                                 if(i < size-1)
12256                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12257                                                 else
12258                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12259                                         }
12260                                 } else {
12261                                         // copy regs
12262
12263                                         for(i=0;i<size;i++) {
12264                                                 if(i < size-1)
12265                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12266                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12267                                                 else
12268                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12269                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12270                                         }
12271                                 }
12272                                 goto release;
12273                         } 
12274                         // right = ACC
12275                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12276                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12277                         goto release;
12278         } // if (AOP_TYPE(result) != AOP_IMMD)
12279
12280         } // if (AOP_TYPE(result) != AOP_STR)
12281         /* so dptr know contains the address */
12282
12283
12284         /* if bit then unpack */
12285         if (IS_BITFIELD(retype)) 
12286                 genPackBits(retype,result,right,"dptr",GPOINTER);
12287         else {
12288                 size = AOP_SIZE(right);
12289                 offset = 0 ;
12290
12291                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12292
12293                 // set up FSR0 with address of result
12294                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12295                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12296         
12297                 while (size--) {
12298                         if (AOP_TYPE(right) == AOP_LIT) {
12299                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12300                                 if (size) {
12301                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12302                                 } else {
12303                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12304                                 }
12305                         } else { // no literal
12306                                 if(size) {
12307                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12308                                 } else {
12309                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12310                                 }
12311                         }
12312                         offset++;
12313                 }
12314         }
12315
12316         release:
12317         pic16_freeAsmop(right,NULL,ic,TRUE);
12318         pic16_freeAsmop(result,NULL,ic,TRUE);
12319 }
12320 #endif
12321
12322 static void genGenPointerSet (operand *right,
12323                               operand *result, iCode *ic)
12324 {
12325   int size;
12326   sym_link *retype = getSpec(operandType(right));
12327   char fgptrput[32];
12328
12329     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12330
12331     pic16_aopOp(result,ic,FALSE);
12332     pic16_aopOp(right,ic,FALSE);
12333     size = AOP_SIZE(right);
12334
12335     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12336
12337
12338     /* if bit then unpack */
12339     if (IS_BITFIELD(retype)) {
12340 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12341       genPackBits(retype,result,right,"dptr",GPOINTER);
12342       goto release;
12343     }
12344
12345     size = AOP_SIZE(right);
12346
12347     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12348
12349
12350
12351     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12352
12353     /* value of right+0 is placed on stack, which will be retrieved
12354      * by the support function this restoring the stack. The important
12355      * thing is that there is no need to manually restore stack pointer
12356      * here */
12357     pushaop(AOP(right), 0);
12358 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12359     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12360     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12361     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12362     
12363     /* load address to write to in WREG:FSR0H:FSR0L */
12364     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12365                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12366     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12367                                 pic16_popCopyReg(&pic16_pc_prodl)));
12368     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12369     
12370
12371     /* put code here */
12372     switch (size) {
12373       case 1: strcpy(fgptrput, "__gptrput1"); break;
12374       case 2: strcpy(fgptrput, "__gptrput2"); break;
12375       case 3: strcpy(fgptrput, "__gptrput3"); break;
12376       case 4: strcpy(fgptrput, "__gptrput4"); break;
12377       default:
12378         werror(W_POSSBUG2, __FILE__, __LINE__);
12379         abort();
12380     }
12381     
12382     pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12383     
12384     {
12385       symbol *sym;
12386                   
12387         sym = newSymbol( fgptrput, 0 );
12388         strcpy(sym->rname, fgptrput);
12389         checkAddSym(&externs, sym);
12390     }
12391
12392 release:
12393     pic16_freeAsmop(right,NULL,ic,TRUE);
12394     pic16_freeAsmop(result,NULL,ic,TRUE);
12395 }
12396
12397 /*-----------------------------------------------------------------*/
12398 /* genPointerSet - stores the value into a pointer location        */
12399 /*-----------------------------------------------------------------*/
12400 static void genPointerSet (iCode *ic)
12401 {    
12402   operand *right, *result ;
12403   sym_link *type, *etype;
12404   int p_type;
12405
12406     FENTRY;
12407
12408     right = IC_RIGHT(ic);
12409     result = IC_RESULT(ic) ;
12410
12411     /* depending on the type of pointer we need to
12412     move it to the correct pointer register */
12413     type = operandType(result);
12414     etype = getSpec(type);
12415     /* if left is of type of pointer then it is simple */
12416     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12417         p_type = DCL_TYPE(type);
12418     }
12419     else {
12420         /* we have to go by the storage class */
12421         p_type = PTR_TYPE(SPEC_OCLS(etype));
12422
12423 /*      if (SPEC_OCLS(etype)->codesp ) { */
12424 /*          p_type = CPOINTER ;  */
12425 /*      } */
12426 /*      else */
12427 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12428 /*              p_type = FPOINTER ; */
12429 /*          else */
12430 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12431 /*                  p_type = PPOINTER ; */
12432 /*              else */
12433 /*                  if (SPEC_OCLS(etype) == idata ) */
12434 /*                      p_type = IPOINTER ; */
12435 /*                  else */
12436 /*                      p_type = POINTER ; */
12437     }
12438
12439     /* now that we have the pointer type we assign
12440     the pointer values */
12441     switch (p_type) {
12442       case POINTER:
12443       case IPOINTER:
12444         genNearPointerSet (right,result,ic);
12445         break;
12446
12447       case PPOINTER:
12448         genPagedPointerSet (right,result,ic);
12449         break;
12450
12451       case FPOINTER:
12452         genFarPointerSet (right,result,ic);
12453         break;
12454         
12455       case GPOINTER:
12456         genGenPointerSet (right,result,ic);
12457         break;
12458
12459       default:
12460         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12461           "genPointerSet: illegal pointer type");
12462     }
12463 }
12464
12465 /*-----------------------------------------------------------------*/
12466 /* genIfx - generate code for Ifx statement                        */
12467 /*-----------------------------------------------------------------*/
12468 static void genIfx (iCode *ic, iCode *popIc)
12469 {
12470   operand *cond = IC_COND(ic);
12471   int isbit =0;
12472
12473     FENTRY;
12474
12475     pic16_aopOp(cond,ic,FALSE);
12476
12477     /* get the value into acc */
12478     if (AOP_TYPE(cond) != AOP_CRY)
12479       pic16_toBoolean(cond);
12480     else
12481       isbit = 1;
12482     /* the result is now in the accumulator */
12483     pic16_freeAsmop(cond,NULL,ic,TRUE);
12484
12485     /* if there was something to be popped then do it */
12486     if (popIc)
12487       genIpop(popIc);
12488
12489     /* if the condition is  a bit variable */
12490     if (isbit && IS_ITEMP(cond) && 
12491         SPIL_LOC(cond)) {
12492       genIfxJump(ic,"c");
12493       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12494     } else {
12495       if (isbit && !IS_ITEMP(cond))
12496         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12497         else
12498         genIfxJump(ic,"a");
12499     }
12500     ic->generated = 1;
12501 }
12502
12503 /*-----------------------------------------------------------------*/
12504 /* genAddrOf - generates code for address of                       */
12505 /*-----------------------------------------------------------------*/
12506 static void genAddrOf (iCode *ic)
12507 {
12508   operand *result, *left;
12509   int size;
12510   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12511   pCodeOp *pcop0, *pcop1, *pcop2;
12512
12513     FENTRY;
12514
12515     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12516
12517     sym = OP_SYMBOL( IC_LEFT(ic) );
12518     
12519     if(sym->onStack) {
12520       /* get address of symbol on stack */
12521       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12522 #if 0
12523       fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12524                   OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12525 #endif
12526
12527       // operands on stack are accessible via "FSR2 + index" with index
12528       // starting at 2 for arguments and growing from 0 downwards for
12529       // local variables (index == 0 is not assigned so we add one here)
12530       {
12531         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12532         if (soffs <= 0) {
12533           assert (soffs < 0);
12534           soffs++;
12535         } // if
12536         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12537         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12538         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12539         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12540         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12541         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12542         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12543       }
12544
12545       goto release;
12546     }
12547         
12548 //      if(pic16_debug_verbose) {
12549 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12550 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12551 //      }
12552         
12553     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12554     size = AOP_SIZE(IC_RESULT(ic));
12555
12556     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12557     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12558     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12559         
12560     if (size == 3) {
12561       pic16_emitpcode(POC_MOVLW, pcop0);
12562       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12563       pic16_emitpcode(POC_MOVLW, pcop1);
12564       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12565       pic16_emitpcode(POC_MOVLW, pcop2);
12566       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12567     } else
12568     if (size == 2) {
12569       pic16_emitpcode(POC_MOVLW, pcop0);
12570       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12571       pic16_emitpcode(POC_MOVLW, pcop1);
12572     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12573     } else {
12574       pic16_emitpcode(POC_MOVLW, pcop0);
12575       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12576     }
12577
12578     pic16_freeAsmop(left, NULL, ic, FALSE);
12579 release:
12580     pic16_freeAsmop(result,NULL,ic,TRUE);
12581 }
12582
12583
12584 #if 0
12585 /*-----------------------------------------------------------------*/
12586 /* genFarFarAssign - assignment when both are in far space         */
12587 /*-----------------------------------------------------------------*/
12588 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12589 {
12590     int size = AOP_SIZE(right);
12591     int offset = 0;
12592     char *l ;
12593     /* first push the right side on to the stack */
12594     while (size--) {
12595         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12596         MOVA(l);
12597         pic16_emitcode ("push","acc");
12598     }
12599     
12600     pic16_freeAsmop(right,NULL,ic,FALSE);
12601     /* now assign DPTR to result */
12602     pic16_aopOp(result,ic,FALSE);
12603     size = AOP_SIZE(result);
12604     while (size--) {
12605         pic16_emitcode ("pop","acc");
12606         pic16_aopPut(AOP(result),"a",--offset);
12607     }
12608     pic16_freeAsmop(result,NULL,ic,FALSE);
12609         
12610 }
12611 #endif
12612
12613 /*-----------------------------------------------------------------*/
12614 /* genAssign - generate code for assignment                        */
12615 /*-----------------------------------------------------------------*/
12616 static void genAssign (iCode *ic)
12617 {
12618   operand *result, *right;
12619   int size, offset,know_W;
12620   unsigned long lit = 0L;
12621
12622   result = IC_RESULT(ic);
12623   right  = IC_RIGHT(ic) ;
12624
12625   FENTRY;
12626   
12627   /* if they are the same */
12628   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12629     return ;
12630
12631   /* reversed order operands are aopOp'ed so that result operand
12632    * is effective in case right is a stack symbol. This maneauver
12633    * allows to use the _G.resDirect flag later */
12634   pic16_aopOp(result,ic,TRUE);
12635   pic16_aopOp(right,ic,FALSE);
12636
12637   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12638
12639   /* if they are the same registers */
12640   if (pic16_sameRegs(AOP(right),AOP(result)))
12641     goto release;
12642
12643   /* if the result is a bit */
12644   if (AOP_TYPE(result) == AOP_CRY) {
12645     /* if the right size is a literal then
12646        we know what the value is */
12647     if (AOP_TYPE(right) == AOP_LIT) {
12648           
12649       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12650                   pic16_popGet(AOP(result),0));
12651
12652       if (((int) operandLitValue(right))) 
12653         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12654                        AOP(result)->aopu.aop_dir,
12655                        AOP(result)->aopu.aop_dir);
12656       else
12657         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12658                        AOP(result)->aopu.aop_dir,
12659                        AOP(result)->aopu.aop_dir);
12660       goto release;
12661     }
12662
12663     /* the right is also a bit variable */
12664     if (AOP_TYPE(right) == AOP_CRY) {
12665       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12666       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12667       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12668
12669       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12670                      AOP(result)->aopu.aop_dir,
12671                      AOP(result)->aopu.aop_dir);
12672       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12673                      AOP(right)->aopu.aop_dir,
12674                      AOP(right)->aopu.aop_dir);
12675       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12676                      AOP(result)->aopu.aop_dir,
12677                      AOP(result)->aopu.aop_dir);
12678       goto release ;
12679     }
12680
12681     /* we need to or */
12682     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12683     pic16_toBoolean(right);
12684     emitSKPZ;
12685     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12686     //pic16_aopPut(AOP(result),"a",0);
12687     goto release ;
12688   }
12689
12690   /* bit variables done */
12691   /* general case */
12692   size = AOP_SIZE(result);
12693   offset = 0 ;
12694
12695   if(AOP_TYPE(right) == AOP_LIT) {
12696         if(!IS_FLOAT(operandType( right )))
12697                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12698         else {
12699            union {
12700               unsigned long lit_int;
12701               float lit_float;
12702             } info;
12703         
12704                 /* take care if literal is a float */
12705                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12706                 lit = info.lit_int;
12707         }
12708   }
12709
12710 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12711 //                      sizeof(unsigned long int), sizeof(float));
12712
12713
12714   if (AOP_TYPE(right) == AOP_REG) {
12715     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12716     while (size--) {
12717       
12718       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12719     } // while
12720     goto release;
12721   }
12722
12723   if(AOP_TYPE(right) != AOP_LIT
12724         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12725         && !IS_FUNC(OP_SYM_TYPE(right))
12726         ) {
12727         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12728         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12729
12730         // set up table pointer
12731         if(is_LitOp(right)) {
12732 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12733                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12734                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12735                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12736                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12737                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12738                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12739         } else {
12740 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12741                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12742                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12743                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12744                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12745                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12746                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12747         }
12748
12749         size = min(AOP_SIZE(right), AOP_SIZE(result));
12750         while(size--) {
12751                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12752                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12753                         pic16_popGet(AOP(result),offset)));
12754                 offset++;
12755         }
12756
12757         if(AOP_SIZE(result) > AOP_SIZE(right)) {
12758                 size = AOP_SIZE(result) - AOP_SIZE(right);
12759                 while(size--) {
12760                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12761                         offset++;
12762                 }
12763         }
12764         goto release;
12765   }
12766
12767
12768
12769 #if 0
12770 /* VR - What is this?! */
12771   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12772     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12773     if(aopIdx(AOP(result),0) == 4) {
12774
12775       /* this is a workaround to save value of right into wreg too,
12776        * value of wreg is going to be used later */
12777       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12778       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12779       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12780       goto release;
12781     } else
12782 //      assert(0);
12783       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12784   }
12785 #endif
12786
12787   know_W=-1;
12788   while (size--) {
12789   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12790     if(AOP_TYPE(right) == AOP_LIT) {
12791       if(lit&0xff) {
12792         if(know_W != (lit&0xff))
12793           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12794         know_W = lit&0xff;
12795         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12796       } else
12797         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12798
12799       lit >>= 8;
12800
12801     } else if (AOP_TYPE(right) == AOP_CRY) {
12802       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12803       if(offset == 0) {
12804         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12805         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12806         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12807       }
12808     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12809         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12810         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12811     } else {
12812       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12813
12814       if(!_G.resDirect)         /* use this aopForSym feature */
12815         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12816     }
12817             
12818     offset++;
12819   }
12820   
12821  release:
12822   pic16_freeAsmop (right,NULL,ic,FALSE);
12823   pic16_freeAsmop (result,NULL,ic,TRUE);
12824 }   
12825
12826 /*-----------------------------------------------------------------*/
12827 /* genJumpTab - generates code for jump table                       */
12828 /*-----------------------------------------------------------------*/
12829 static void genJumpTab (iCode *ic)
12830 {
12831   symbol *jtab;
12832   char *l;
12833   pCodeOp *jt_offs;
12834   pCodeOp *jt_offs_hi;
12835   pCodeOp *jt_label;
12836
12837     FENTRY;
12838
12839     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12840     /* get the condition into accumulator */
12841     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12842     MOVA(l);
12843     /* multiply by three */
12844     pic16_emitcode("add","a,acc");
12845     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12846
12847     jtab = newiTempLabel(NULL);
12848     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12849     pic16_emitcode("jmp","@a+dptr");
12850     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12851
12852 #if 0
12853     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12854     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12855     emitSKPNC;
12856     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12857     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12858     pic16_emitpLabel(jtab->key);
12859
12860 #else
12861
12862     jt_offs = pic16_popGetTempReg(0);
12863     jt_offs_hi = pic16_popGetTempReg(1);
12864     jt_label = pic16_popGetLabel (jtab->key);
12865     //fprintf (stderr, "Creating jump table...\n");
12866
12867     // calculate offset into jump table (idx * sizeof (GOTO))
12868     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12869     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12870     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12871     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12872     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12873     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12874     pic16_emitpcode(POC_MOVWF , jt_offs);
12875
12876     // prepare PCLATx (set to first entry in jump table)
12877     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12878     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12879     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12880     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12881     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12882
12883     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12884     pic16_emitpcode(POC_ADDWF , jt_offs);
12885     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12886     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12887     emitSKPNC;
12888     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12889
12890     // release temporaries and prepare jump into table (new PCL --> WREG)
12891     pic16_emitpcode(POC_MOVFW , jt_offs);
12892     pic16_popReleaseTempReg (jt_offs_hi, 1);
12893     pic16_popReleaseTempReg (jt_offs, 0);
12894
12895     // jump into the table
12896     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12897
12898     pic16_emitpLabelFORCE(jtab->key);
12899
12900 #endif
12901     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12902
12903     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12904     /* now generate the jump labels */
12905     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12906          jtab = setNextItem(IC_JTLABELS(ic))) {
12907 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12908         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12909         
12910     }
12911     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12912
12913 }
12914
12915 /*-----------------------------------------------------------------*/
12916 /* genMixedOperation - gen code for operators between mixed types  */
12917 /*-----------------------------------------------------------------*/
12918 /*
12919   TSD - Written for the PIC port - but this unfortunately is buggy.
12920   This routine is good in that it is able to efficiently promote 
12921   types to different (larger) sizes. Unfortunately, the temporary
12922   variables that are optimized out by this routine are sometimes
12923   used in other places. So until I know how to really parse the 
12924   iCode tree, I'm going to not be using this routine :(.
12925 */
12926 static int genMixedOperation (iCode *ic)
12927 {
12928 #if 0
12929   operand *result = IC_RESULT(ic);
12930   sym_link *ctype = operandType(IC_LEFT(ic));
12931   operand *right = IC_RIGHT(ic);
12932   int ret = 0;
12933   int big,small;
12934   int offset;
12935
12936   iCode *nextic;
12937   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12938
12939   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12940
12941   nextic = ic->next;
12942   if(!nextic)
12943     return 0;
12944
12945   nextright = IC_RIGHT(nextic);
12946   nextleft  = IC_LEFT(nextic);
12947   nextresult = IC_RESULT(nextic);
12948
12949   pic16_aopOp(right,ic,FALSE);
12950   pic16_aopOp(result,ic,FALSE);
12951   pic16_aopOp(nextright,  nextic, FALSE);
12952   pic16_aopOp(nextleft,   nextic, FALSE);
12953   pic16_aopOp(nextresult, nextic, FALSE);
12954
12955   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12956
12957     operand *t = right;
12958     right = nextright;
12959     nextright = t; 
12960
12961     pic16_emitcode(";remove right +","");
12962
12963   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12964 /*
12965     operand *t = right;
12966     right = nextleft;
12967     nextleft = t; 
12968 */
12969     pic16_emitcode(";remove left +","");
12970   } else
12971     return 0;
12972
12973   big = AOP_SIZE(nextleft);
12974   small = AOP_SIZE(nextright);
12975
12976   switch(nextic->op) {
12977
12978   case '+':
12979     pic16_emitcode(";optimize a +","");
12980     /* if unsigned or not an integral type */
12981     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12982       pic16_emitcode(";add a bit to something","");
12983     } else {
12984
12985       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12986
12987       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12988         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12989         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12990       } else
12991         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12992
12993       offset = 0;
12994       while(--big) {
12995
12996         offset++;
12997
12998         if(--small) {
12999           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13000             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13001             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13002           }
13003
13004           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13005           emitSKPNC;
13006           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13007                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13008                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13009           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13010           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13011
13012         } else {
13013           pic16_emitcode("rlf","known_zero,w");
13014
13015           /*
13016             if right is signed
13017               btfsc  right,7
13018                addlw ff
13019           */
13020           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13021             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13022             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13023           } else {
13024             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13025           }
13026         }
13027       }
13028       ret = 1;
13029     }
13030   }
13031   ret = 1;
13032
13033 release:
13034   pic16_freeAsmop(right,NULL,ic,TRUE);
13035   pic16_freeAsmop(result,NULL,ic,TRUE);
13036   pic16_freeAsmop(nextright,NULL,ic,TRUE);
13037   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13038   if(ret)
13039     nextic->generated = 1;
13040
13041   return ret;
13042 #else
13043   return 0;
13044 #endif
13045 }
13046 /*-----------------------------------------------------------------*/
13047 /* genCast - gen code for casting                                  */
13048 /*-----------------------------------------------------------------*/
13049 static void genCast (iCode *ic)
13050 {
13051   operand *result = IC_RESULT(ic);
13052   sym_link *ctype = operandType(IC_LEFT(ic));
13053   sym_link *rtype = operandType(IC_RIGHT(ic));
13054   sym_link *restype = operandType(IC_RESULT(ic));
13055   operand *right = IC_RIGHT(ic);
13056   int size, offset ;
13057
13058
13059     FENTRY;
13060
13061         /* if they are equivalent then do nothing */
13062 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13063 //              return ;
13064
13065         pic16_aopOp(right,ic,FALSE) ;
13066         pic16_aopOp(result,ic,FALSE);
13067
13068         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13069
13070
13071         /* if the result is a bit */
13072         if (AOP_TYPE(result) == AOP_CRY) {
13073         
13074                 /* if the right size is a literal then
13075                  * we know what the value is */
13076                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13077
13078                 if (AOP_TYPE(right) == AOP_LIT) {
13079                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13080                                 pic16_popGet(AOP(result),0));
13081
13082                         if (((int) operandLitValue(right))) 
13083                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13084                                         AOP(result)->aopu.aop_dir,
13085                                         AOP(result)->aopu.aop_dir);
13086                         else
13087                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13088                                         AOP(result)->aopu.aop_dir,
13089                                         AOP(result)->aopu.aop_dir);
13090                         goto release;
13091                 }
13092
13093                 /* the right is also a bit variable */
13094                 if (AOP_TYPE(right) == AOP_CRY) {
13095                         emitCLRC;
13096                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13097
13098                         pic16_emitcode("clrc","");
13099                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13100                                 AOP(right)->aopu.aop_dir,
13101                                 AOP(right)->aopu.aop_dir);
13102                         pic16_aopPut(AOP(result),"c",0);
13103                         goto release ;
13104                 }
13105
13106                 /* we need to or */
13107                 if (AOP_TYPE(right) == AOP_REG) {
13108                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
13109                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13110                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
13111                 }
13112                 pic16_toBoolean(right);
13113                 pic16_aopPut(AOP(result),"a",0);
13114                 goto release ;
13115         }
13116
13117         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13118           int offset = 1;
13119
13120                 size = AOP_SIZE(result);
13121
13122                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13123
13124                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
13125                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13126                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
13127
13128                 while (size--)
13129                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13130
13131                 goto release;
13132         }
13133
13134         if(IS_BITFIELD(getSpec(restype))
13135           && IS_BITFIELD(getSpec(rtype))) {
13136           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13137         }
13138
13139         /* if they are the same size : or less */
13140         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13141
13142                 /* if they are in the same place */
13143                 if (pic16_sameRegs(AOP(right),AOP(result)))
13144                         goto release;
13145
13146                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13147 #if 0
13148                 if (IS_PTR_CONST(rtype))
13149 #else
13150                 if (IS_CODEPTR(rtype))
13151 #endif
13152                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13153
13154 #if 0
13155                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13156 #else
13157                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13158 #endif
13159                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13160
13161 #if 0
13162                 if(AOP_TYPE(right) == AOP_IMMD) {
13163                   pCodeOp *pcop0, *pcop1, *pcop2;
13164                   symbol *sym = OP_SYMBOL( right );
13165
13166                         size = AOP_SIZE(result);
13167                         /* low */
13168                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13169                         /* high */
13170                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13171                         /* upper */
13172                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13173         
13174                         if (size == 3) {
13175                                 pic16_emitpcode(POC_MOVLW, pcop0);
13176                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13177                                 pic16_emitpcode(POC_MOVLW, pcop1);
13178                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13179                                 pic16_emitpcode(POC_MOVLW, pcop2);
13180                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13181                         } else
13182                         if (size == 2) {
13183                                 pic16_emitpcode(POC_MOVLW, pcop0);
13184                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13185                                 pic16_emitpcode(POC_MOVLW, pcop1);
13186                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13187                         } else {
13188                                 pic16_emitpcode(POC_MOVLW, pcop0);
13189                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13190                         }
13191                 } else
13192 #endif
13193                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13194                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13195                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13196                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13197                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13198                         if(AOP_SIZE(result) <2)
13199                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13200                 } else {
13201                         /* if they in different places then copy */
13202                         size = AOP_SIZE(result);
13203                         offset = 0 ;
13204                         while (size--) {
13205                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13206                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13207                                 offset++;
13208                         }
13209                 }
13210                 goto release;
13211         }
13212
13213         /* if the result is of type pointer */
13214         if (IS_PTR(ctype)) {
13215           int p_type;
13216           sym_link *type = operandType(right);
13217           sym_link *etype = getSpec(type);
13218
13219                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13220
13221                 /* pointer to generic pointer */
13222                 if (IS_GENPTR(ctype)) {
13223                   char *l = zero;
13224             
13225                         if (IS_PTR(type)) 
13226                                 p_type = DCL_TYPE(type);
13227                         else {
13228                 /* we have to go by the storage class */
13229                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13230
13231 /*              if (SPEC_OCLS(etype)->codesp )  */
13232 /*                  p_type = CPOINTER ;  */
13233 /*              else */
13234 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13235 /*                      p_type = FPOINTER ; */
13236 /*                  else */
13237 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13238 /*                          p_type = PPOINTER; */
13239 /*                      else */
13240 /*                          if (SPEC_OCLS(etype) == idata ) */
13241 /*                              p_type = IPOINTER ; */
13242 /*                          else */
13243 /*                              p_type = POINTER ; */
13244             }
13245                 
13246             /* the first two bytes are known */
13247       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13248             size = GPTRSIZE - 1; 
13249             offset = 0 ;
13250             while (size--) {
13251               if(offset < AOP_SIZE(right)) {
13252                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13253                 mov2f(AOP(result), AOP(right), offset);
13254 /*
13255                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13256                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13257                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13258                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13259                 } else { 
13260                   
13261                   pic16_aopPut(AOP(result),
13262                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13263                          offset);
13264                 }
13265 */
13266               } else 
13267                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13268               offset++;
13269             }
13270             /* the last byte depending on type */
13271             switch (p_type) {
13272             case IPOINTER:
13273             case POINTER:
13274                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13275                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13276 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13277                 break;
13278
13279             case CPOINTER:
13280                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13281                 break;
13282
13283             case FPOINTER:
13284               pic16_emitcode(";BUG!? ","%d",__LINE__);
13285                 l = one;
13286                 break;
13287             case PPOINTER:
13288               pic16_emitcode(";BUG!? ","%d",__LINE__);
13289                 l = "#0x03";
13290                 break;
13291
13292             case GPOINTER:
13293                 if (GPTRSIZE > AOP_SIZE(right)) {
13294                   // assume data pointer... THIS MIGHT BE WRONG!
13295                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13296                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13297                 } else {
13298                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13299                 }
13300               break;
13301               
13302             default:
13303                 /* this should never happen */
13304                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13305                        "got unknown pointer type");
13306                 exit(1);
13307             }
13308             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13309             goto release ;
13310         }
13311         
13312         /* just copy the pointers */
13313         size = AOP_SIZE(result);
13314         offset = 0 ;
13315         while (size--) {
13316             pic16_aopPut(AOP(result),
13317                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13318                    offset);
13319             offset++;
13320         }
13321         goto release ;
13322     }
13323     
13324
13325
13326     /* so we now know that the size of destination is greater
13327     than the size of the source.
13328     Now, if the next iCode is an operator then we might be
13329     able to optimize the operation without performing a cast.
13330     */
13331     if(genMixedOperation(ic))
13332       goto release;
13333
13334     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13335     
13336     /* we move to result for the size of source */
13337     size = AOP_SIZE(right);
13338     offset = 0 ;
13339     while (size--) {
13340       mov2f(AOP(result), AOP(right), offset);
13341       offset++;
13342     }
13343
13344     /* now depending on the sign of the destination */
13345     size = AOP_SIZE(result) - AOP_SIZE(right);
13346     /* if unsigned or not an integral type */
13347     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13348       while (size--)
13349         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13350     } else {
13351       /* we need to extend the sign :( */
13352
13353       if(size == 1) {
13354         /* Save one instruction of casting char to int */
13355         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13356         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13357         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
13358       } else {
13359         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13360
13361         if(offset)
13362           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13363         else
13364           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13365         
13366         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13367
13368         while (size--)
13369           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13370       }
13371     }
13372
13373 release:
13374     pic16_freeAsmop(right,NULL,ic,TRUE);
13375     pic16_freeAsmop(result,NULL,ic,TRUE);
13376
13377 }
13378
13379 /*-----------------------------------------------------------------*/
13380 /* genDjnz - generate decrement & jump if not zero instrucion      */
13381 /*-----------------------------------------------------------------*/
13382 static int genDjnz (iCode *ic, iCode *ifx)
13383 {
13384     symbol *lbl, *lbl1;
13385     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13386
13387     if (!ifx)
13388         return 0;
13389     
13390     /* if the if condition has a false label
13391        then we cannot save */
13392     if (IC_FALSE(ifx))
13393         return 0;
13394
13395     /* if the minus is not of the form 
13396        a = a - 1 */
13397     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13398         !IS_OP_LITERAL(IC_RIGHT(ic)))
13399         return 0;
13400
13401     if (operandLitValue(IC_RIGHT(ic)) != 1)
13402         return 0;
13403
13404     /* if the size of this greater than one then no
13405        saving */
13406     if (getSize(operandType(IC_RESULT(ic))) > 1)
13407         return 0;
13408
13409     /* otherwise we can save BIG */
13410     lbl = newiTempLabel(NULL);
13411     lbl1= newiTempLabel(NULL);
13412
13413     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13414     
13415     if (IS_AOP_PREG(IC_RESULT(ic))) {
13416         pic16_emitcode("dec","%s",
13417                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13418         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13419         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13420     } else {    
13421
13422
13423       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13424       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13425
13426       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13427       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13428
13429     }
13430     
13431     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13432     ifx->generated = 1;
13433     return 1;
13434 }
13435
13436 /*-----------------------------------------------------------------*/
13437 /* genReceive - generate code for a receive iCode                  */
13438 /*-----------------------------------------------------------------*/
13439 static void genReceive (iCode *ic)
13440 {    
13441
13442   FENTRY;
13443
13444 #if 0
13445   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13446         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13447 #endif
13448 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13449
13450   if (isOperandInFarSpace(IC_RESULT(ic))
13451       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13452           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13453
13454     int size = getSize(operandType(IC_RESULT(ic)));
13455     int offset =  pic16_fReturnSizePic - size;
13456
13457       assert( 0 );
13458       while (size--) {
13459         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13460                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13461                       offset++;
13462         }
13463
13464       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13465
13466       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13467       size = AOP_SIZE(IC_RESULT(ic));
13468       offset = 0;
13469       while (size--) {
13470         pic16_emitcode ("pop","acc");
13471         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13472       }
13473   } else {
13474     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13475     _G.accInUse++;
13476     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13477     _G.accInUse--;
13478
13479     /* set pseudo stack pointer to where it should be - dw*/
13480     GpsuedoStkPtr = ic->parmBytes;
13481
13482     /* setting GpsuedoStkPtr has side effects here: */
13483     assignResultValue(IC_RESULT(ic), 0);
13484   }
13485
13486   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13487 }
13488
13489 /*-----------------------------------------------------------------*/
13490 /* genDummyRead - generate code for dummy read of volatiles        */
13491 /*-----------------------------------------------------------------*/
13492 static void
13493 genDummyRead (iCode * ic)
13494 {
13495   pic16_emitcode ("; genDummyRead","");
13496   pic16_emitcode ("; not implemented","");
13497
13498   ic = ic;
13499 }
13500
13501 /*-----------------------------------------------------------------*/
13502 /* genpic16Code - generate code for pic16 based controllers        */
13503 /*-----------------------------------------------------------------*/
13504 /*
13505  * At this point, ralloc.c has gone through the iCode and attempted
13506  * to optimize in a way suitable for a PIC. Now we've got to generate
13507  * PIC instructions that correspond to the iCode.
13508  *
13509  * Once the instructions are generated, we'll pass through both the
13510  * peep hole optimizer and the pCode optimizer.
13511  *-----------------------------------------------------------------*/
13512
13513 void genpic16Code (iCode *lic)
13514 {
13515   iCode *ic;
13516   int cln = 0;
13517
13518     lineHead = lineCurr = NULL;
13519
13520     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13521     pic16_addpBlock(pb);
13522
13523 #if 0
13524     /* if debug information required */
13525     if (options.debug && currFunc) {
13526       if (currFunc) {
13527         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13528       }
13529     }
13530 #endif
13531
13532     for (ic = lic ; ic ; ic = ic->next ) {
13533
13534       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13535       if ( cln != ic->lineno ) {
13536         if ( options.debug ) {
13537           debugFile->writeCLine (ic);
13538         }
13539         
13540         if(!options.noCcodeInAsm) {
13541           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13542               printCLine(ic->filename, ic->lineno)));
13543         }
13544
13545         cln = ic->lineno ;
13546       }
13547         
13548       if(options.iCodeInAsm) {
13549         char *l;
13550
13551           /* insert here code to print iCode as comment */
13552           l = Safe_strdup(printILine(ic));
13553           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13554       }
13555         
13556       /* if the result is marked as
13557        * spilt and rematerializable or code for
13558        * this has already been generated then
13559        * do nothing */
13560       if (resultRemat(ic) || ic->generated ) 
13561         continue ;
13562         
13563       /* depending on the operation */
13564       switch (ic->op) {
13565         case '!' :
13566           pic16_genNot(ic);
13567           break;
13568             
13569         case '~' :
13570           pic16_genCpl(ic);
13571           break;
13572             
13573         case UNARYMINUS:
13574           genUminus (ic);
13575           break;
13576             
13577         case IPUSH:
13578           genIpush (ic);
13579           break;
13580             
13581         case IPOP:
13582           /* IPOP happens only when trying to restore a 
13583            * spilt live range, if there is an ifx statement
13584            * following this pop then the if statement might
13585            * be using some of the registers being popped which
13586            * would destroy the contents of the register so
13587            * we need to check for this condition and handle it */
13588            if (ic->next
13589              && ic->next->op == IFX
13590              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13591                genIfx (ic->next,ic);
13592           else
13593             genIpop (ic);
13594           break; 
13595             
13596         case CALL:
13597           genCall (ic);
13598           break;
13599             
13600         case PCALL:
13601           genPcall (ic);
13602           break;
13603             
13604         case FUNCTION:
13605           genFunction (ic);
13606           break;
13607             
13608         case ENDFUNCTION:
13609           genEndFunction (ic);
13610           break;
13611             
13612         case RETURN:
13613           genRet (ic);
13614           break;
13615             
13616         case LABEL:
13617           genLabel (ic);
13618           break;
13619             
13620         case GOTO:
13621           genGoto (ic);
13622           break;
13623             
13624         case '+' :
13625           pic16_genPlus (ic) ;
13626           break;
13627             
13628         case '-' :
13629           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13630             pic16_genMinus (ic);
13631           break;
13632
13633         case '*' :
13634           genMult (ic);
13635           break;
13636             
13637         case '/' :
13638           genDiv (ic) ;
13639           break;
13640             
13641         case '%' :
13642           genMod (ic);
13643           break;
13644             
13645         case '>' :
13646           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13647           break;
13648             
13649         case '<' :
13650           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13651           break;
13652             
13653         case LE_OP:
13654         case GE_OP:
13655         case NE_OP:
13656           /* note these two are xlated by algebraic equivalence
13657            * during parsing SDCC.y */
13658           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13659             "got '>=' or '<=' shouldn't have come here");
13660           break;
13661
13662         case EQ_OP:
13663           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13664           break;            
13665             
13666         case AND_OP:
13667           genAndOp (ic);
13668           break;
13669             
13670         case OR_OP:
13671           genOrOp (ic);
13672           break;
13673             
13674         case '^' :
13675           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13676           break;
13677             
13678         case '|' :
13679           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13680           break;
13681             
13682         case BITWISEAND:
13683           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13684           break;
13685             
13686         case INLINEASM:
13687           genInline (ic);
13688           break;
13689             
13690         case RRC:
13691           genRRC (ic);
13692           break;
13693             
13694         case RLC:
13695           genRLC (ic);
13696           break;
13697             
13698         case GETHBIT:
13699           genGetHbit (ic);
13700           break;
13701             
13702         case LEFT_OP:
13703           genLeftShift (ic);
13704           break;
13705             
13706         case RIGHT_OP:
13707           genRightShift (ic);
13708           break;
13709             
13710         case GET_VALUE_AT_ADDRESS:
13711           genPointerGet(ic);
13712           break;
13713             
13714         case '=' :
13715           if (POINTER_SET(ic))
13716             genPointerSet(ic);
13717           else
13718             genAssign(ic);
13719           break;
13720             
13721         case IFX:
13722           genIfx (ic,NULL);
13723           break;
13724             
13725         case ADDRESS_OF:
13726           genAddrOf (ic);
13727           break;
13728             
13729         case JUMPTABLE:
13730           genJumpTab (ic);
13731           break;
13732             
13733         case CAST:
13734           genCast (ic);
13735           break;
13736             
13737         case RECEIVE:
13738           genReceive(ic);
13739           break;
13740             
13741         case SEND:
13742           addSet(&_G.sendSet,ic);
13743           break;
13744
13745         case DUMMY_READ_VOLATILE:
13746           genDummyRead (ic);
13747           break;
13748
13749         default :
13750           ic = ic;
13751       }
13752     }
13753
13754
13755     /* now we are ready to call the
13756        peep hole optimizer */
13757     if (!options.nopeep)
13758       peepHole (&lineHead);
13759
13760     /* now do the actual printing */
13761     printLine (lineHead, codeOutFile);
13762
13763 #ifdef PCODE_DEBUG
13764     DFPRINTF((stderr,"printing pBlock\n\n"));
13765     pic16_printpBlock(stdout,pb);
13766 #endif
13767
13768     return;
13769 }
13770