* src/pic16/device.c (Pics16[]): added devices 18F2550, 18F4331,
[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,2005)
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 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
139 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
140 static char **fReturn = fReturnpic16;
141
142 static char *accUse[] = {"WREG"};
143
144 //static short rbank = -1;
145
146 static struct {
147     short r0Pushed;
148     short r1Pushed;
149     short fsr0Pushed;
150     short accInUse;
151     short inLine;
152     short debugLine;
153     short nRegsSaved;
154     short ipushRegs;
155     set *sendSet;
156     set *stackRegSet;
157     int usefastretfie;
158     bitVect *fregsUsed;                 /* registers used in function */
159     bitVect *sregsAlloc;
160     set *sregsAllocSet;                 /* registers used to store stack variables */
161     int stack_lat;                      /* stack offset latency */
162     int resDirect;
163     int useWreg;                        /* flag when WREG is used to pass function parameter */
164 } _G;
165
166 extern int pic16_ptrRegReq ;
167 extern int pic16_nRegs;
168 extern FILE *codeOutFile;
169 //static void saverbank (int, iCode *,bool);
170
171 static lineNode *lineHead = NULL;
172 static lineNode *lineCurr = NULL;
173
174 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
175 0xE0, 0xC0, 0x80, 0x00};
176 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
177 0x07, 0x03, 0x01, 0x00};
178
179 static  pBlock *pb;
180
181 /*-----------------------------------------------------------------*/
182 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
183 /*                 exponent of 2 is returned, otherwise -1 is      */
184 /*                 returned.                                       */
185 /* note that this is similar to the function `powof2' in SDCCsymt  */
186 /* if(n == 2^y)                                                    */
187 /*   return y;                                                     */
188 /* return -1;                                                      */
189 /*-----------------------------------------------------------------*/
190 int pic16_my_powof2 (unsigned long num)
191 {
192   if(num) {
193     if( (num & (num-1)) == 0) {
194       int nshifts = -1;
195       while(num) {
196         num>>=1;
197         nshifts++;
198       }
199       return nshifts;
200     }
201   }
202
203   return -1;
204 }
205
206 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
207 {
208   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
209                        line_no,
210                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
211                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
212                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
213                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
214                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
215                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
216                        ((result) ? AOP_SIZE(result) : 0));
217 }
218
219 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
220 {
221
222   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
223                        line_no,
224                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
225                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
226                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
227                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
228                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
229                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
230
231 }
232
233 void pic16_emitpcomment (char *fmt, ...)
234 {
235     va_list ap;
236     char lb[INITIAL_INLINEASM];  
237     char *lbp = lb;
238
239     va_start(ap,fmt);   
240
241     lb[0] = ';';
242     vsprintf(lb+1,fmt,ap);
243
244     while (isspace(*lbp)) lbp++;
245
246     if (lbp && *lbp) 
247         lineCurr = (lineCurr ?
248                     connectLine(lineCurr,newLineNode(lb)) :
249                     (lineHead = newLineNode(lb)));
250     lineCurr->isInline = _G.inLine;
251     lineCurr->isDebug  = _G.debugLine;
252
253     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
254     va_end(ap);
255
256 //      fprintf(stderr, "%s\n", lb);
257 }
258
259 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
260 {
261     va_list ap;
262     char lb[INITIAL_INLINEASM];  
263     char *lbp = lb;
264
265     if(!pic16_debug_verbose)
266       return;
267
268     va_start(ap,fmt);   
269
270     if (inst && *inst) {
271         if (fmt && *fmt)
272             sprintf(lb,"%s\t",inst);
273         else
274             sprintf(lb,"%s",inst);
275         vsprintf(lb+(strlen(lb)),fmt,ap);
276     }  else
277         vsprintf(lb,fmt,ap);
278
279     while (isspace(*lbp)) lbp++;
280
281     if (lbp && *lbp) 
282         lineCurr = (lineCurr ?
283                     connectLine(lineCurr,newLineNode(lb)) :
284                     (lineHead = newLineNode(lb)));
285     lineCurr->isInline = _G.inLine;
286     lineCurr->isDebug  = _G.debugLine;
287
288     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
289     va_end(ap);
290
291 //      fprintf(stderr, "%s\n", lb);
292 }
293
294
295
296 void pic16_emitpLabel(int key)
297 {
298   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
299 }
300
301 void pic16_emitpLabelFORCE(int key)
302 {
303   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
304 }
305
306 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
307 {
308
309   if(pcop)
310     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
311   else
312     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
313 }
314
315 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
316 {
317   if(pcop)
318     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
319   else
320     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
321 }
322   
323 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
324 {
325
326   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
327
328 }
329
330
331 #if 1
332 #define pic16_emitcode  DEBUGpic16_emitcode
333 #else
334 /*-----------------------------------------------------------------*/
335 /* pic16_emitcode - writes the code into a file : for now it is simple    */
336 /*-----------------------------------------------------------------*/
337 void pic16_emitcode (char *inst,char *fmt, ...)
338 {
339     va_list ap;
340     char lb[INITIAL_INLINEASM];  
341     char *lbp = lb;
342
343     va_start(ap,fmt);   
344
345     if (inst && *inst) {
346         if (fmt && *fmt)
347             sprintf(lb,"%s\t",inst);
348         else
349             sprintf(lb,"%s",inst);
350         vsprintf(lb+(strlen(lb)),fmt,ap);
351     }  else
352         vsprintf(lb,fmt,ap);
353
354     while (isspace(*lbp)) lbp++;
355
356     if (lbp && *lbp) 
357         lineCurr = (lineCurr ?
358                     connectLine(lineCurr,newLineNode(lb)) :
359                     (lineHead = newLineNode(lb)));
360     lineCurr->isInline = _G.inLine;
361     lineCurr->isDebug  = _G.debugLine;
362
363 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
364
365 //    if(pic16_debug_verbose)
366 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
367
368     va_end(ap);
369 }
370 #endif
371
372
373 /*-----------------------------------------------------------------*/
374 /* pic16_emitDebuggerSymbol - associate the current code location  */
375 /*   with a debugger symbol                                        */
376 /*-----------------------------------------------------------------*/
377 void
378 pic16_emitDebuggerSymbol (char * debugSym)
379 {
380   _G.debugLine = 1;
381   pic16_emitcode (";", "%s ==.", debugSym);
382   _G.debugLine = 0;
383 }
384
385
386 /*-----------------------------------------------------------------*/
387 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
388 /*-----------------------------------------------------------------*/
389 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
390 {
391 //    bool r0iu = FALSE , r1iu = FALSE;
392 //    bool r0ou = FALSE , r1ou = FALSE;
393     bool fsr0iu = FALSE, fsr0ou;
394     bool fsr2iu = FALSE, fsr2ou;
395     
396     fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
397
398     
399     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
400     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
401     
402     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
403     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
404
405     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
406         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
407         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
408     }
409
410     if(!fsr0iu && !fsr0ou) {
411         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
412         (*aopp)->type = AOP_FSR0;
413
414         fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
415         
416       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
417     }
418
419 #if 0
420     /* no usage of FSR2 */
421     if(!fsr2iu && !fsr2ou) {
422         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
423         (*aopp)->type = AOP_FSR2;
424
425       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
426     }
427 #endif
428         
429     /* now we know they both have usage */
430     /* if fsr0 not used in this instruction */
431     if (!fsr0iu) {
432         if (!_G.fsr0Pushed) {
433                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
434                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
435                 _G.fsr0Pushed++;
436         }
437
438         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
439         (*aopp)->type = AOP_FSR0;
440
441 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
442
443       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
444     }
445         
446
447     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
448     assert( 0 );
449
450     return NULL;
451 #if 0
452     /* the logic: if r0 & r1 used in the instruction
453     then we are in trouble otherwise */
454
455     /* first check if r0 & r1 are used by this
456     instruction, in which case we are in trouble */
457     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
458         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
459     {
460         goto endOfWorld;      
461     }
462
463     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
464     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
465
466     /* if no usage of r0 then return it */
467     if (!r0iu && !r0ou) {
468         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
469         (*aopp)->type = AOP_R0; 
470         
471         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
472     }
473
474     /* if no usage of r1 then return it */
475     if (!r1iu && !r1ou) {
476         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
477         (*aopp)->type = AOP_R1;
478
479         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
480     }    
481
482     /* now we know they both have usage */
483     /* if r0 not used in this instruction */
484     if (!r0iu) {
485         /* push it if not already pushed */
486         if (!_G.r0Pushed) {
487           //pic16_emitcode ("push","%s",
488           //          pic16_regWithIdx(R0_IDX)->dname);
489             _G.r0Pushed++ ;
490         }
491         
492         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
493         (*aopp)->type = AOP_R0;
494
495         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
496     }
497
498     /* if r1 not used then */
499
500     if (!r1iu) {
501         /* push it if not already pushed */
502         if (!_G.r1Pushed) {
503           //pic16_emitcode ("push","%s",
504           //          pic16_regWithIdx(R1_IDX)->dname);
505             _G.r1Pushed++ ;
506         }
507         
508         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
509         (*aopp)->type = AOP_R1;
510         return pic16_regWithIdx(R1_IDX);
511     }
512
513 endOfWorld :
514     /* I said end of world but not quite end of world yet */
515     /* if this is a result then we can push it on the stack*/
516     if (result) {
517         (*aopp)->type = AOP_STK;    
518         return NULL;
519     }
520
521     /* other wise this is true end of the world */
522     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
523            "getFreePtr should never reach here");
524     exit(0);
525 #endif
526 }
527
528 /*-----------------------------------------------------------------*/
529 /* newAsmop - creates a new asmOp                                  */
530 /*-----------------------------------------------------------------*/
531 static asmop *newAsmop (short type)
532 {
533     asmop *aop;
534
535     aop = Safe_calloc(1,sizeof(asmop));
536     aop->type = type;
537     return aop;
538 }
539
540 static void genSetDPTR(int n)
541 {
542     if (!n)
543     {
544         pic16_emitcode(";", "Select standard DPTR");
545         pic16_emitcode("mov", "dps, #0x00");
546     }
547     else
548     {
549         pic16_emitcode(";", "Select alternate DPTR");
550         pic16_emitcode("mov", "dps, #0x01");
551     }
552 }
553
554 /*-----------------------------------------------------------------*/
555 /* resolveIfx - converts an iCode ifx into a form more useful for  */
556 /*              generating code                                    */
557 /*-----------------------------------------------------------------*/
558 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
559 {
560   FENTRY2;
561   
562 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
563
564   if(!resIfx) 
565     return;
566
567
568   resIfx->condition = 1;    /* assume that the ifx is true */
569   resIfx->generated = 0;    /* indicate that the ifx has not been used */
570
571   if(!ifx) {
572     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
573
574 #if 1
575     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
576                         __FUNCTION__,__LINE__,resIfx->lbl->key);
577 #endif
578
579   } else {
580     if(IC_TRUE(ifx)) {
581       resIfx->lbl = IC_TRUE(ifx);
582     } else {
583       resIfx->lbl = IC_FALSE(ifx);
584       resIfx->condition = 0;
585     }
586
587 #if 1
588     if(IC_TRUE(ifx)) 
589       DEBUGpic16_emitcode("; +++","ifx true is non-null");
590     else
591       DEBUGpic16_emitcode("; +++","ifx true is null");
592     if(IC_FALSE(ifx)) 
593       DEBUGpic16_emitcode("; +++","ifx false is non-null");
594     else
595       DEBUGpic16_emitcode("; +++","ifx false is null");
596 #endif
597   }
598
599   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
600
601 }
602 #if 0
603 /*-----------------------------------------------------------------*/
604 /* pointerCode - returns the code for a pointer type               */
605 /*-----------------------------------------------------------------*/
606 static int pointerCode (sym_link *etype)
607 {
608
609     return PTR_TYPE(SPEC_OCLS(etype));
610
611 }
612 #endif
613
614 /*-----------------------------------------------------------------*/
615 /* aopForSym - for a true symbol                                   */
616 /*-----------------------------------------------------------------*/
617 static asmop *aopForSym (iCode *ic, operand *op, bool result)
618 {
619     symbol *sym=OP_SYMBOL(op);
620     asmop *aop;
621     memmap *space= SPEC_OCLS(sym->etype);
622
623     FENTRY2;
624     
625     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
626     
627 //    sym = OP_SYMBOL(op);
628
629     /* if already has one */
630     if (sym->aop) {
631             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
632         return sym->aop;
633     }
634
635 #if 0
636     /* if symbol was initially placed onStack then we must re-place it
637      * to direct memory, since pic16 does not have a specific stack */
638     if(sym->onStack) {
639         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
640     }
641 #endif
642
643
644 #if 0
645     if(sym->iaccess) {
646       if(space->paged) {
647         fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
648
649         sym->aop = aop = newAsmop (AOP_PAGED);
650         aop->aopu.aop_dir = sym->rname ;
651         aop->size = getSize(sym->type);
652         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
653         pic16_allocDirReg( IC_LEFT(ic) );
654         return aop;
655       }
656       assert( 0 );
657     }
658 #endif
659     
660 #if 1
661     /* assign depending on the storage class */
662     /* if it is on the stack or indirectly addressable */
663     /* space we need to assign either r0 or r1 to it   */    
664     if (sym->onStack)   // || sym->iaccess)
665     {
666       pCodeOp *pcop[4];
667       int i;
668       
669         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
670                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
671         
672         /* acquire a temporary register -- it is saved in function */
673
674         sym->aop = aop = newAsmop(AOP_STA);
675         aop->aopu.stk.stk = sym->stack;
676         aop->size = getSize(sym->type);
677
678
679         DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
680         if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
681           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
682 //          pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
683           
684           for(i=0;i<aop->size;i++)
685             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
686             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
687         } else
688         if(1 && ic->op == SEND) {
689
690           /* if SEND do the send here */
691           _G.resDirect = 1;
692         } else {
693           for(i=0;i<aop->size;i++) {
694             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
695             _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
696           }
697         }
698
699
700 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
701
702 #if 1
703         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
704
705         // we do not need to load the value if it is to be defined...
706         if (result) return aop;
707
708         if(_G.accInUse) {
709                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
710         }
711         
712         for(i=0;i<aop->size;i++) {
713
714           /* initialise for stack access via frame pointer */
715           // operands on stack are accessible via "FSR2 + index" with index
716           // starting at 2 for arguments and growing from 0 downwards for
717           // local variables (index == 0 is not assigned so we add one here)
718           {
719             int soffs = sym->stack;
720             if (soffs <= 0) {
721               assert (soffs < 0);
722               soffs++;
723             } // if
724
725             if(1 && ic->op == SEND) {
726               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
727               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
728                     pic16_popCopyReg( pic16_frame_plusw ),
729                     pic16_popCopyReg(pic16_stack_postdec )));
730             } else {
731               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
732               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
733                   pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
734             }
735           }
736         }
737         
738         if(_G.accInUse) {
739                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
740         }
741         
742         return (aop);
743 #endif
744
745 #if 0
746         /* now assign the address of the variable to 
747         the pointer register */
748         if (aop->type != AOP_STK) {
749
750             if (sym->onStack) {
751                     if ( _G.accInUse )
752                         pic16_emitcode("push","acc");
753
754                     pic16_emitcode("mov","a,_bp");
755                     pic16_emitcode("add","a,#0x%02x",
756                              ((sym->stack < 0) ?
757                               ((char)(sym->stack - _G.nRegsSaved )) :
758                               ((char)sym->stack)) & 0xff);
759                     pic16_emitcode("mov","%s,a",
760                              aop->aopu.aop_ptr->name);
761
762                     if ( _G.accInUse )
763                         pic16_emitcode("pop","acc");
764             } else
765                 pic16_emitcode("mov","%s,#%s",
766                          aop->aopu.aop_ptr->name,
767                          sym->rname);
768             aop->paged = space->paged;
769         } else
770             aop->aopu.aop_stk = sym->stack;
771         return aop;
772 #endif
773
774     }
775 #endif
776
777 #if 0
778     if (sym->onStack && options.stack10bit)
779     {
780         /* It's on the 10 bit stack, which is located in
781          * far data space.
782          */
783          
784       //DEBUGpic16_emitcode(";","%d",__LINE__);
785
786         if ( _G.accInUse )
787                 pic16_emitcode("push","acc");
788
789         pic16_emitcode("mov","a,_bp");
790         pic16_emitcode("add","a,#0x%02x",
791                  ((sym->stack < 0) ?
792                    ((char)(sym->stack - _G.nRegsSaved )) :
793                    ((char)sym->stack)) & 0xff);
794         
795         genSetDPTR(1);
796         pic16_emitcode ("mov","dpx1,#0x40");
797         pic16_emitcode ("mov","dph1,#0x00");
798         pic16_emitcode ("mov","dpl1, a");
799         genSetDPTR(0);
800         
801         if ( _G.accInUse )
802             pic16_emitcode("pop","acc");
803             
804         sym->aop = aop = newAsmop(AOP_DPTR2);
805         aop->size = getSize(sym->type); 
806         return aop;
807     }
808 #endif
809
810 #if 1
811     /* special case for a function */
812     if (IS_FUNC(sym->type)) {   
813         sym->aop = aop = newAsmop(AOP_PCODE);
814         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
815         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
816         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
817         PCOI(aop->aopu.pcop)->index = 0;
818         aop->size = FPTRSIZE; 
819         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
820         return aop;
821     }
822 #endif
823
824
825
826     //DEBUGpic16_emitcode(";","%d",__LINE__);
827     /* if in bit space */
828     if (IN_BITSPACE(space)) {
829         sym->aop = aop = newAsmop (AOP_CRY);
830         aop->aopu.aop_dir = sym->rname ;
831         aop->size = getSize(sym->type);
832         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
833         return aop;
834     }
835     /* if it is in direct space */
836     if (IN_DIRSPACE(space)) {
837         sym->aop = aop = newAsmop (AOP_DIR);
838         aop->aopu.aop_dir = sym->rname ;
839         aop->size = getSize(sym->type);
840         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
841         pic16_allocDirReg( IC_LEFT(ic) );
842         return aop;
843     }
844
845
846     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
847         sym->aop = aop = newAsmop (AOP_DIR);
848         aop->aopu.aop_dir = sym->rname ;
849         aop->size = getSize(sym->type);
850         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
851         pic16_allocDirReg( IC_LEFT(ic) );
852         return aop;
853     }
854
855
856     /* only remaining is far space */
857     sym->aop = aop = newAsmop(AOP_PCODE);
858
859 /* change the next if to 1 to revert to good old immediate code */
860         if(IN_CODESPACE(space)) {
861                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
862                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
863                 PCOI(aop->aopu.pcop)->index = 0;
864         } else {
865                 /* try to allocate via direct register */
866                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
867 //              aop->size = getSize( sym->type );
868         }
869
870         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
871                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
872
873 #if 0
874         if(!pic16_allocDirReg (IC_LEFT(ic)))
875                 return NULL;
876 #endif
877
878         if(IN_DIRSPACE( space ))
879                 aop->size = PTRSIZE;
880         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
881                 aop->size = FPTRSIZE;
882         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
883         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
884         else if(sym->onStack) {
885                 aop->size = PTRSIZE;
886         } else {
887           if(SPEC_SCLS(sym->etype) == S_PDATA) {
888             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
889             aop->size = FPTRSIZE;
890           } else
891                 assert( 0 );
892         }
893
894     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
895
896     /* if it is in code space */
897     if (IN_CODESPACE(space))
898         aop->code = 1;
899
900     return aop;     
901 }
902
903 /*-----------------------------------------------------------------*/
904 /* aopForRemat - rematerialzes an object                           */
905 /*-----------------------------------------------------------------*/
906 static asmop *aopForRemat (operand *op) // x symbol *sym)
907 {
908   symbol *sym = OP_SYMBOL(op);
909   operand *refop;
910   iCode *ic = NULL, *oldic;
911   asmop *aop = newAsmop(AOP_PCODE);
912   int val = 0;
913   int offset = 0;
914   int viaimmd=0;
915
916     FENTRY2;
917     
918         ic = sym->rematiCode;
919
920         if(IS_OP_POINTER(op)) {
921                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
922         }
923
924         for (;;) {
925                 oldic = ic;
926
927 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
928         
929                 if (ic->op == '+') {
930                         val += (int) operandLitValue(IC_RIGHT(ic));
931                 } else if (ic->op == '-') {
932                         val -= (int) operandLitValue(IC_RIGHT(ic));
933                 } else
934                         break;
935                 
936                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
937         }
938
939         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
940         refop = IC_LEFT(ic);
941
942         if(!op->isaddr)viaimmd++; else viaimmd=0;
943                 
944 /* set the following if to 1 to revert to good old immediate code */
945         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
946                 || viaimmd) {
947
948                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
949
950                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
951
952 #if 0
953                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
954 #else
955                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
956 #endif
957
958                 PCOI(aop->aopu.pcop)->index = val;
959                 
960                 aop->size = getSize( sym->type );
961         } else {
962                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
963
964                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
965                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
966
967                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
968         }
969
970
971         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
972                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
973 #if 0
974                 val, IS_PTR_CONST(operandType(op)));
975 #else
976                 val, IS_CODEPTR(operandType(op)));
977 #endif
978
979 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
980
981         pic16_allocDirReg (IC_LEFT(ic));
982
983         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
984                 aop->code = 1;
985
986   return aop;        
987 }
988
989 #if 0
990 static int aopIdx (asmop *aop, int offset)
991 {
992   if(!aop)
993     return -1;
994
995   if(aop->type !=  AOP_REG)
996     return -2;
997         
998   return aop->aopu.aop_reg[offset]->rIdx;
999
1000 }
1001 #endif
1002
1003 /*-----------------------------------------------------------------*/
1004 /* regsInCommon - two operands have some registers in common       */
1005 /*-----------------------------------------------------------------*/
1006 static bool regsInCommon (operand *op1, operand *op2)
1007 {
1008     symbol *sym1, *sym2;
1009     int i;
1010
1011     /* if they have registers in common */
1012     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1013         return FALSE ;
1014
1015     sym1 = OP_SYMBOL(op1);
1016     sym2 = OP_SYMBOL(op2);
1017
1018     if (sym1->nRegs == 0 || sym2->nRegs == 0)
1019         return FALSE ;
1020
1021     for (i = 0 ; i < sym1->nRegs ; i++) {
1022         int j;
1023         if (!sym1->regs[i])
1024             continue ;
1025
1026         for (j = 0 ; j < sym2->nRegs ;j++ ) {
1027             if (!sym2->regs[j])
1028                 continue ;
1029
1030             if (sym2->regs[j] == sym1->regs[i])
1031                 return TRUE ;
1032         }
1033     }
1034
1035     return FALSE ;
1036 }
1037
1038 /*-----------------------------------------------------------------*/
1039 /* operandsEqu - equivalent                                        */
1040 /*-----------------------------------------------------------------*/
1041 static bool operandsEqu ( operand *op1, operand *op2)
1042 {
1043     symbol *sym1, *sym2;
1044
1045     /* if they not symbols */
1046     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1047         return FALSE;
1048
1049     sym1 = OP_SYMBOL(op1);
1050     sym2 = OP_SYMBOL(op2);
1051
1052     /* if both are itemps & one is spilt
1053        and the other is not then false */
1054     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1055         sym1->isspilt != sym2->isspilt )
1056         return FALSE ;
1057
1058     /* if they are the same */
1059     if (sym1 == sym2)
1060         return TRUE ;
1061
1062     if (sym1->rname[0] && sym2->rname[0]
1063         && strcmp (sym1->rname, sym2->rname) == 0)
1064         return TRUE;
1065
1066
1067     /* if left is a tmp & right is not */
1068     if (IS_ITEMP(op1)  && 
1069         !IS_ITEMP(op2) &&
1070         sym1->isspilt  &&
1071         (sym1->usl.spillLoc == sym2))
1072         return TRUE;
1073
1074     if (IS_ITEMP(op2)  && 
1075         !IS_ITEMP(op1) &&
1076         sym2->isspilt  &&
1077         sym1->level > 0 &&
1078         (sym2->usl.spillLoc == sym1))
1079         return TRUE ;
1080
1081     return FALSE ;
1082 }
1083
1084 /*-----------------------------------------------------------------*/
1085 /* pic16_sameRegs - two asmops have the same registers                   */
1086 /*-----------------------------------------------------------------*/
1087 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1088 {
1089     int i;
1090
1091     if (aop1 == aop2)
1092         return TRUE ;
1093
1094     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1095                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1096
1097     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1098
1099     if (aop1->type != AOP_REG ||
1100         aop2->type != AOP_REG )
1101         return FALSE ;
1102
1103     /* This is a bit too restrictive if one is a subset of the other...
1104     if (aop1->size != aop2->size )
1105         return FALSE ;
1106     */
1107
1108     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1109 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1110
1111 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1112         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1113             return FALSE ;
1114     }
1115
1116     return TRUE ;
1117 }
1118
1119 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1120 {
1121     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1122                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1123
1124     if(aop1 == aop2)return TRUE;
1125     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1126       
1127       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1128     
1129   return TRUE;
1130 }
1131
1132
1133 /*-----------------------------------------------------------------*/
1134 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1135 /*-----------------------------------------------------------------*/
1136 void pic16_aopOp (operand *op, iCode *ic, bool result)
1137 {
1138     asmop *aop;
1139     symbol *sym;
1140     int i;
1141
1142     if (!op)
1143         return ;
1144
1145     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1146
1147     /* if this a literal */
1148     if (IS_OP_LITERAL(op)) {
1149         op->aop = aop = newAsmop(AOP_LIT);
1150         aop->aopu.aop_lit = op->operand.valOperand;
1151         aop->size = getSize(operandType(op));
1152         return;
1153     }
1154
1155     {
1156       sym_link *type = operandType(op);
1157 #if 0
1158       if(IS_PTR_CONST(type))
1159 #else
1160       if(IS_CODEPTR(type))
1161 #endif
1162         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1163     }
1164
1165     /* if already has a asmop then continue */
1166     if (op->aop)
1167         return ;
1168
1169     /* if the underlying symbol has a aop */
1170     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1171       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1172         op->aop = OP_SYMBOL(op)->aop;
1173         return;
1174     }
1175
1176     /* if this is a true symbol */
1177     if (IS_TRUE_SYMOP(op)) {    
1178         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1179       op->aop = aopForSym(ic, op, result);
1180       return ;
1181     }
1182
1183     /* this is a temporary : this has
1184     only four choices :
1185     a) register
1186     b) spillocation
1187     c) rematerialize 
1188     d) conditional   
1189     e) can be a return use only */
1190
1191     sym = OP_SYMBOL(op);
1192
1193     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1194     /* if the type is a conditional */
1195     if (sym->regType == REG_CND) {
1196         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1197         aop->size = 0;
1198         return;
1199     }
1200
1201     /* if it is spilt then two situations
1202     a) is rematerialize 
1203     b) has a spill location */
1204     if (sym->isspilt || sym->nRegs == 0) {
1205
1206 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1207       DEBUGpic16_emitcode(";","%d",__LINE__);
1208         /* rematerialize it NOW */
1209         if (sym->remat) {
1210
1211             sym->aop = op->aop = aop = aopForRemat (op);
1212 //            aop->size = getSize(sym->type);
1213 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1214             return;
1215         }
1216
1217 #if 1
1218         if (sym->accuse) {
1219             int i;
1220             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1221             aop->size = getSize(sym->type);
1222             for ( i = 0 ; i < 1 ; i++ ) {
1223                 aop->aopu.aop_str[i] = accUse[i];
1224 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1225             }
1226             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1227             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1228             return;  
1229         }
1230 #endif
1231
1232 #if 1
1233         if (sym->ruonly) {
1234           /*
1235           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1236           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1237           //pic16_allocDirReg (IC_LEFT(ic));
1238           aop->size = getSize(sym->type);
1239           */
1240
1241           unsigned i;
1242
1243           aop = op->aop = sym->aop = newAsmop(AOP_REG);
1244           aop->size = getSize(sym->type);
1245           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1246             aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1247
1248           DEBUGpic16_emitcode(";","%d",__LINE__);
1249           return;
1250         }
1251 #endif
1252         /* else spill location  */
1253         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1254             /* force a new aop if sizes differ */
1255             sym->usl.spillLoc->aop = NULL;
1256         }
1257
1258 #if 0
1259         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1260                             __FUNCTION__,__LINE__,
1261                             sym->usl.spillLoc->rname,
1262                             sym->rname, sym->usl.spillLoc->offset);
1263 #endif
1264
1265         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1266         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1267         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1268           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1269                                                   getSize(sym->type), 
1270                                                   sym->usl.spillLoc->offset, op);
1271         } else {
1272           fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1273           DEBUGpic16_emitcode (";","%s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1274           assert (getSize(sym->type) <= 1);
1275           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1276         }
1277         aop->size = getSize(sym->type);
1278
1279         return;
1280     }
1281
1282     {
1283       sym_link *type = operandType(op);
1284 #if 0
1285       if(IS_PTR_CONST(type)) 
1286 #else
1287       if(IS_CODEPTR(type)) 
1288 #endif
1289         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1290     }
1291
1292     /* must be in a register */
1293     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1294     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1295     aop->size = sym->nRegs;
1296     for ( i = 0 ; i < sym->nRegs ;i++)
1297         aop->aopu.aop_reg[i] = sym->regs[i];
1298 }
1299
1300 /*-----------------------------------------------------------------*/
1301 /* pic16_freeAsmop - free up the asmop given to an operand               */
1302 /*----------------------------------------------------------------*/
1303 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1304 {   
1305     asmop *aop ;
1306
1307     if (!op)
1308         aop = aaop;
1309     else 
1310         aop = op->aop;
1311
1312     if (!aop)
1313         return ;
1314
1315     if (aop->freed)
1316         goto dealloc; 
1317
1318     aop->freed = 1;
1319
1320     /* depending on the asmop type only three cases need work AOP_RO
1321        , AOP_R1 && AOP_STK */
1322 #if 1
1323     switch (aop->type) {
1324         case AOP_FSR0 :
1325             if (_G.fsr0Pushed ) {
1326                 if (pop) {
1327                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1328                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1329 //                    pic16_emitcode ("pop","ar0");
1330                     _G.fsr0Pushed--;
1331                 }
1332             }
1333             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1334             break;
1335
1336         case AOP_FSR2 :
1337             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1338             break;
1339
1340         case AOP_R0 :
1341             if (_G.r0Pushed ) {
1342                 if (pop) {
1343                     pic16_emitcode ("pop","ar0");     
1344                     _G.r0Pushed--;
1345                 }
1346             }
1347             bitVectUnSetBit(ic->rUsed,R0_IDX);
1348             break;
1349
1350         case AOP_R1 :
1351             if (_G.r1Pushed ) {
1352                 if (pop) {
1353                     pic16_emitcode ("pop","ar1");
1354                     _G.r1Pushed--;
1355                 }
1356             }
1357             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1358             break;
1359
1360         case AOP_STA:
1361           {
1362             int i;
1363
1364               /* we must store the result on stack */
1365               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1366                 // operands on stack are accessible via "FSR2 + index" with index
1367                 // starting at 2 for arguments and growing from 0 downwards for
1368                 // local variables (index == 0 is not assigned so we add one here)
1369                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1370                 if (soffs <= 0) {
1371                   assert (soffs < 0);
1372                   soffs++;
1373                 } // if
1374                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1375                 for(i=0;i<aop->size;i++) {
1376                   /* initialise for stack access via frame pointer */
1377                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1378                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1379                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1380                 }
1381         
1382                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1383               }
1384
1385               if(!_G.resDirect) {
1386                 for(i=0;i<aop->size;i++) {
1387                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1388
1389                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx))
1390                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1391                 }
1392                   
1393               }
1394               _G.resDirect = 0;
1395           }
1396           break;
1397 #if 0
1398         case AOP_STK :
1399         {
1400             int sz = aop->size;    
1401             int stk = aop->aopu.aop_stk + aop->size;
1402             bitVectUnSetBit(ic->rUsed,R0_IDX);
1403             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1404
1405             getFreePtr(ic,&aop,FALSE);
1406             
1407             if (options.stack10bit)
1408             {
1409                 /* I'm not sure what to do here yet... */
1410                 /* #STUB */
1411                 fprintf(stderr, 
1412                         "*** Warning: probably generating bad code for "
1413                         "10 bit stack mode.\n");
1414             }
1415             
1416             if (stk) {
1417                 pic16_emitcode ("mov","a,_bp");
1418                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1419                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1420             } else {
1421                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1422             }
1423
1424             while (sz--) {
1425                 pic16_emitcode("pop","acc");
1426                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1427                 if (!sz) break;
1428                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1429             }
1430             op->aop = aop;
1431             pic16_freeAsmop(op,NULL,ic,TRUE);
1432             if (_G.r0Pushed) {
1433                 pic16_emitcode("pop","ar0");
1434                 _G.r0Pushed--;
1435             }
1436
1437             if (_G.r1Pushed) {
1438                 pic16_emitcode("pop","ar1");
1439                 _G.r1Pushed--;
1440             }       
1441         }
1442 #endif
1443
1444     }
1445 #endif
1446
1447 dealloc:
1448     /* all other cases just dealloc */
1449     if (op ) {
1450         op->aop = NULL;
1451         if (IS_SYMOP(op)) {
1452             OP_SYMBOL(op)->aop = NULL;    
1453             /* if the symbol has a spill */
1454             if (SPIL_LOC(op))
1455                 SPIL_LOC(op)->aop = NULL;
1456         }
1457     }
1458 }
1459
1460 /*-----------------------------------------------------------------*/
1461 /* pic16_aopGet - for fetching value of the aop                          */
1462 /*-----------------------------------------------------------------*/
1463 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1464 {
1465     char *s = buffer ;
1466     char *rs;
1467
1468     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1469
1470     /* offset is greater than size then zero */
1471     if (offset > (aop->size - 1) &&
1472         aop->type != AOP_LIT)
1473         return zero;
1474
1475     /* depending on type */
1476     switch (aop->type) {
1477
1478     case AOP_FSR0:
1479     case AOP_FSR2:
1480       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1481       rs = Safe_calloc(1, strlen(s)+1);
1482       strcpy(rs, s);
1483       return (rs);
1484       
1485 #if 0
1486       /* if we need to increment it */
1487       while (offset > aop->coff)
1488         {
1489           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1490           aop->coff++;
1491         }
1492
1493       while (offset < aop->coff)
1494         {
1495           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1496           aop->coff--;
1497         }
1498       aop->coff = offset;
1499       if (aop->paged)
1500         {
1501           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1502           return (dname ? "acc" : "a");
1503         }
1504       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1505       rs = Safe_calloc (1, strlen (s) + 1);
1506       strcpy (rs, s);
1507       return rs;
1508 #endif
1509
1510         
1511     case AOP_IMMD:
1512         if (bit16) 
1513             sprintf (s,"%s",aop->aopu.aop_immd);
1514         else
1515             if (offset) 
1516                 sprintf(s,"(%s >> %d)",
1517                         aop->aopu.aop_immd,
1518                         offset*8);
1519             else
1520                 sprintf(s,"%s",
1521                         aop->aopu.aop_immd);
1522         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1523         rs = Safe_calloc(1,strlen(s)+1);
1524         strcpy(rs,s);   
1525         return rs;
1526         
1527     case AOP_DIR:
1528       if (offset) {
1529         sprintf(s,"(%s + %d)",
1530                 aop->aopu.aop_dir,
1531                 offset);
1532         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1533       } else
1534             sprintf(s,"%s",aop->aopu.aop_dir);
1535         rs = Safe_calloc(1,strlen(s)+1);
1536         strcpy(rs,s);   
1537         return rs;
1538         
1539     case AOP_REG:
1540       //if (dname) 
1541       //    return aop->aopu.aop_reg[offset]->dname;
1542       //else
1543             return aop->aopu.aop_reg[offset]->name;
1544         
1545     case AOP_CRY:
1546       //pic16_emitcode(";","%d",__LINE__);
1547       return aop->aopu.aop_dir;
1548         
1549     case AOP_ACC:
1550         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1551 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1552 //        assert( 0 );
1553 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1554         rs = Safe_strdup("WREG");
1555         return (rs);
1556
1557     case AOP_LIT:
1558         sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1559         rs = Safe_calloc(1,strlen(s)+1);
1560         strcpy(rs,s);   
1561         return rs;
1562         
1563     case AOP_STR:
1564         aop->coff = offset ;
1565
1566 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1567 //          dname)
1568 //          return "acc";
1569         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1570           aop->type = AOP_ACC;
1571           return Safe_strdup("WREG");
1572         }
1573         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1574         
1575         return aop->aopu.aop_str[offset];
1576         
1577     case AOP_PCODE:
1578       {
1579         pCodeOp *pcop = aop->aopu.pcop;
1580         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1581         if(pcop->name) {
1582           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1583           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1584           if (offset) {
1585             sprintf(s,"(%s + %d)", pcop->name, offset);
1586           } else {
1587             sprintf(s,"%s", pcop->name);
1588           }
1589         } else
1590           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1591
1592       }
1593       rs = Safe_calloc(1,strlen(s)+1);
1594       strcpy(rs,s);   
1595       return rs;
1596
1597 #if 0
1598     case AOP_PAGED:
1599       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1600       if (offset) {
1601         sprintf(s,"(%s + %d)",
1602                 aop->aopu.aop_dir,
1603                 offset);
1604       } else
1605             sprintf(s,"%s",aop->aopu.aop_dir);
1606       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1607       rs = Safe_calloc(1,strlen(s)+1);
1608       strcpy(rs,s);   
1609       return rs;
1610 #endif
1611
1612     case AOP_STA:
1613         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1614         return (rs);
1615         
1616     case AOP_STK:
1617 //        pCodeOp *pcop = aop->aop
1618         break;
1619
1620     }
1621
1622     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1623     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1624            "aopget got unsupported aop->type");
1625     exit(0);
1626 }
1627
1628
1629
1630 /* lock has the following meaning: When allocating temporary registers
1631  * for stack variables storage, the value of the temporary register is
1632  * saved on stack. Its value is restored at the end. This procedure is
1633  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1634  * a possibility that before a call to pic16_aopOp, a temporary register
1635  * is allocated for a while and it is freed after some time, this will
1636  * mess the stack and values will not be restored properly. So use lock=1
1637  * to allocate temporary registers used internally by the programmer, and
1638  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1639  * to inform the compiler developer about a possible bug. This is an internal
1640  * feature for developing the compiler -- VR */
1641  
1642 int _TempReg_lock = 0;
1643 /*-----------------------------------------------------------------*/
1644 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1645 /*-----------------------------------------------------------------*/
1646 pCodeOp *pic16_popGetTempReg(int lock)
1647 {
1648   pCodeOp *pcop;
1649   symbol *cfunc;
1650
1651 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1652     if(_TempReg_lock) {
1653 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1654     }
1655     
1656     _TempReg_lock += lock;
1657     
1658     cfunc = currFunc;
1659     currFunc = NULL;
1660
1661     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1662     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1663       PCOR(pcop)->r->wasUsed=1;
1664       PCOR(pcop)->r->isFree=0;
1665
1666       /* push value on stack */
1667       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1668     }
1669
1670     currFunc = cfunc;
1671
1672   return pcop;
1673 }
1674
1675 /*-----------------------------------------------------------------*/
1676 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1677 /*                           is not part of f, but don't save if   */
1678 /*                           inside v                              */
1679 /*-----------------------------------------------------------------*/
1680 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1681 {
1682   pCodeOp *pcop=NULL;
1683   symbol *cfunc;
1684   int i;
1685
1686 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1687
1688     if(_TempReg_lock) {
1689 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1690     }
1691
1692     _TempReg_lock += lock;
1693
1694     cfunc = currFunc;
1695     currFunc = NULL;
1696
1697     i = bitVectFirstBit(f);
1698     while(i < 128) {
1699
1700       /* bypass registers that are used by function */
1701       if(!bitVectBitValue(f, i)) {
1702       
1703         /* bypass registers that are already allocated for stack access */
1704         if(!bitVectBitValue(v, i))  {
1705         
1706 //          debugf("getting register rIdx = %d\n", i);
1707           /* ok, get the operand */
1708           pcop = pic16_newpCodeOpReg( i );
1709     
1710           /* should never by NULL */
1711           assert( pcop != NULL );
1712
1713           
1714           /* sanity check */
1715           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1716             int found=0;
1717             
1718               PCOR(pcop)->r->wasUsed=1;
1719               PCOR(pcop)->r->isFree=0;
1720
1721
1722               {
1723                 regs *sr;
1724               
1725                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1726
1727                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1728                       /* already used in previous steps, break */
1729                       found=1;          
1730                       break;
1731                     }
1732                   }
1733               }
1734
1735               /* caller takes care of the following */
1736 //              bitVectSetBit(v, i);
1737
1738               if(!found) {
1739                 /* push value on stack */
1740                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1741                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1742               }
1743           
1744             break;
1745           }
1746         }
1747       }
1748       i++;
1749     }
1750
1751     currFunc = cfunc;
1752
1753   return pcop;
1754 }
1755
1756
1757 /*-----------------------------------------------------------------*/
1758 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1759 /*-----------------------------------------------------------------*/
1760 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1761 {
1762   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1763
1764   _TempReg_lock -= lock;
1765
1766   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1767     PCOR(pcop)->r->isFree = 1;
1768
1769     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1770   }
1771 }
1772 /*-----------------------------------------------------------------*/
1773 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1774 /*-----------------------------------------------------------------*/
1775 pCodeOp *pic16_popGetLabel(unsigned int key)
1776 {
1777
1778   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1779
1780   if(key>max_key)
1781     max_key = key;
1782
1783   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1784 }
1785
1786 /*-----------------------------------------------------------------*/
1787 /* pic16_popCopyReg - copy a pcode operator                              */
1788 /*-----------------------------------------------------------------*/
1789 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1790 {
1791   pCodeOpReg *pcor;
1792
1793   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1794   pcor->pcop.type = pc->pcop.type;
1795   if(pc->pcop.name) {
1796     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1797       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1798   } else
1799     pcor->pcop.name = NULL;
1800
1801   pcor->r = pc->r;
1802   pcor->rIdx = pc->rIdx;
1803   pcor->r->wasUsed=1;
1804   pcor->instance = pc->instance;
1805
1806 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1807
1808   return PCOP(pcor);
1809 }
1810
1811 /*-----------------------------------------------------------------*/
1812 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1813 /*-----------------------------------------------------------------*/
1814 pCodeOp *pic16_popGetLit(int lit)
1815 {
1816   return pic16_newpCodeOpLit(lit);
1817 }
1818
1819 /*-----------------------------------------------------------------*/
1820 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1821 /*-----------------------------------------------------------------*/
1822 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1823 {
1824   return pic16_newpCodeOpLit2(lit, arg2);
1825 }
1826
1827
1828 /*-----------------------------------------------------------------*/
1829 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1830 /*-----------------------------------------------------------------*/
1831 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1832 {
1833   return pic16_newpCodeOpImmd(name, offset,index, 0);
1834 }
1835
1836
1837 /*-----------------------------------------------------------------*/
1838 /* pic16_popGet - asm operator to pcode operator conversion              */
1839 /*-----------------------------------------------------------------*/
1840 pCodeOp *pic16_popGetWithString(char *str)
1841 {
1842   pCodeOp *pcop;
1843
1844
1845   if(!str) {
1846     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1847     exit (1);
1848   }
1849
1850   pcop = pic16_newpCodeOp(str,PO_STR);
1851
1852   return pcop;
1853 }
1854
1855 /*-----------------------------------------------------------------*/
1856 /* pic16_popRegFromString -                                        */
1857 /*-----------------------------------------------------------------*/
1858 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1859 {
1860
1861   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1862   pcop->type = PO_DIR;
1863
1864   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1865   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1866
1867   if(!str)
1868     str = "BAD_STRING";
1869
1870   pcop->name = Safe_calloc(1,strlen(str)+1);
1871   strcpy(pcop->name,str);
1872
1873   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1874
1875   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1876
1877   /* make sure that register doesn't exist,
1878    * and operand isn't NULL
1879    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1880   if((PCOR(pcop)->r == NULL) 
1881     && (op)
1882     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1883 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1884 //              __FUNCTION__, __LINE__, str, size, offset);
1885
1886     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1887     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1888
1889   }
1890   PCOR(pcop)->instance = offset;
1891
1892   return pcop;
1893 }
1894
1895 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1896 {
1897   pCodeOp *pcop;
1898
1899 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1900
1901         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1902         PCOR(pcop)->rIdx = rIdx;
1903         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1904
1905         PCOR(pcop)->r->isFree = 0;
1906         PCOR(pcop)->r->wasUsed = 1;
1907
1908         pcop->type = PCOR(pcop)->r->pc_type;
1909
1910   return pcop;
1911 }
1912
1913 /*---------------------------------------------------------------------------------*/
1914 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1915 /*                 VR 030601                                                       */
1916 /*---------------------------------------------------------------------------------*/
1917 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1918 {
1919   pCodeOpReg2 *pcop2;
1920   pCodeOp *temp;
1921   
1922         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1923
1924         /* comment the following check, so errors to throw up */
1925 //      if(!pcop2)return NULL;
1926
1927         temp = pic16_popGet(aop_dst, offset);
1928         pcop2->pcop2 = temp;
1929         
1930   return PCOP(pcop2);
1931 }
1932
1933
1934
1935 /*--------------------------------------------------------------------------------.-*/
1936 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1937 /*                  VR 030601 , adapted by Hans Dorn                                */
1938 /*--------------------------------------------------------------------------------.-*/
1939 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1940 {
1941   pCodeOpReg2 *pcop2;
1942  
1943         pcop2 = (pCodeOpReg2 *)src;
1944         pcop2->pcop2 = dst;
1945         
1946         return PCOP(pcop2);
1947 }
1948
1949
1950
1951 /*---------------------------------------------------------------------------------*/
1952 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1953 /*                     movff instruction                                           */
1954 /*---------------------------------------------------------------------------------*/
1955 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1956 {
1957   pCodeOpReg2 *pcop2;
1958
1959         if(!noalloc) {
1960                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1961                 pcop2->pcop2 = pic16_popCopyReg(dst);
1962         } else {
1963                 /* the pCodeOp may be already allocated */
1964                 pcop2 = (pCodeOpReg2 *)(src);
1965                 pcop2->pcop2 = (pCodeOp *)(dst);
1966         }
1967
1968   return PCOP(pcop2);
1969 }
1970
1971
1972 /*-----------------------------------------------------------------*/
1973 /* pic16_popGet - asm operator to pcode operator conversion              */
1974 /*-----------------------------------------------------------------*/
1975 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1976 {
1977   //char *s = buffer ;
1978   char *rs;
1979   pCodeOp *pcop;
1980
1981     FENTRY2;
1982     /* offset is greater than
1983     size then zero */
1984
1985 //    if (offset > (aop->size - 1) &&
1986 //        aop->type != AOP_LIT)
1987 //      return NULL;  //zero;
1988
1989     /* depending on type */
1990     switch (aop->type) {
1991         
1992     case AOP_R0:
1993     case AOP_R1:
1994     case AOP_DPTR:
1995     case AOP_DPTR2:
1996         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1997         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1998         assert( 0 );
1999         return NULL;
2000
2001
2002     case AOP_FSR0:
2003     case AOP_FSR2:
2004       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2005       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
2006       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2007       PCOR(pcop)->r->wasUsed = 1;
2008       PCOR(pcop)->r->isFree = 0;
2009       
2010       PCOR(pcop)->instance = offset;
2011       pcop->type = PCOR(pcop)->r->pc_type;
2012       return (pcop);
2013
2014     case AOP_IMMD:
2015       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2016       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2017
2018     case AOP_STA:
2019       /* pCodeOp is already allocated from aopForSym */
2020         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2021         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2022           
2023       return (pcop);
2024       
2025     case AOP_ACC:
2026       {
2027         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
2028
2029         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2030
2031         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2032         
2033         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2034         PCOR(pcop)->rIdx = rIdx;
2035         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2036         PCOR(pcop)->r->wasUsed=1;
2037         PCOR(pcop)->r->isFree=0;
2038
2039         PCOR(pcop)->instance = offset;
2040         pcop->type = PCOR(pcop)->r->pc_type;
2041 //      rs = aop->aopu.aop_reg[offset]->name;
2042 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2043         return pcop;
2044
2045
2046 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2047 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2048
2049 //      assert( 0 );
2050       }
2051         
2052     case AOP_DIR:
2053       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2054       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2055         
2056 #if 0
2057     case AOP_PAGED:
2058       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2059       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2060 #endif
2061
2062     case AOP_REG:
2063       {
2064         int rIdx;
2065         assert (aop && aop->aopu.aop_reg[offset] != NULL);
2066         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2067
2068         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2069         
2070         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2071 //      pcop->type = PO_GPR_REGISTER;
2072         PCOR(pcop)->rIdx = rIdx;
2073         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
2074         PCOR(pcop)->r->wasUsed=1;
2075         PCOR(pcop)->r->isFree=0;
2076
2077         PCOR(pcop)->instance = offset;
2078         pcop->type = PCOR(pcop)->r->pc_type;
2079         
2080         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2081         rs = aop->aopu.aop_reg[offset]->name;
2082         DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2083         return pcop;
2084       }
2085
2086     case AOP_CRY:
2087         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2088
2089       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2090       PCOR(pcop)->instance = offset;
2091       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2092       //if(PCOR(pcop)->r == NULL)
2093       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2094       return pcop;
2095         
2096     case AOP_LIT:
2097         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2098       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2099
2100     case AOP_STR:
2101       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2102       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2103
2104       /*
2105       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2106       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2107       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2108       pcop->type = PCOR(pcop)->r->pc_type;
2109       pcop->name = PCOR(pcop)->r->name;
2110
2111       return pcop;
2112       */
2113
2114     case AOP_PCODE:
2115       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2116                           __LINE__, 
2117                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2118       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2119       switch( aop->aopu.pcop->type ) {
2120         case PO_DIR: PCOR(pcop)->instance += offset; break;
2121         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2122         case PO_WREG:
2123             assert (offset==0);
2124             break;
2125         default:
2126           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2127           assert( 0 );  /* should never reach here */;
2128       }
2129       return pcop;
2130     }
2131
2132     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2133            "pic16_popGet got unsupported aop->type");
2134     exit(0);
2135 }
2136 /*-----------------------------------------------------------------*/
2137 /* pic16_aopPut - puts a string for a aop                                */
2138 /*-----------------------------------------------------------------*/
2139 void pic16_aopPut (asmop *aop, char *s, int offset)
2140 {
2141     char *d = buffer ;
2142     symbol *lbl ;
2143
2144     return;
2145
2146     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2147
2148     if (aop->size && offset > ( aop->size - 1)) {
2149         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2150                "pic16_aopPut got offset > aop->size");
2151         exit(0);
2152     }
2153
2154     /* will assign value to value */
2155     /* depending on where it is ofcourse */
2156     switch (aop->type) {
2157     case AOP_DIR:
2158       if (offset) {
2159         sprintf(d,"(%s + %d)",
2160                 aop->aopu.aop_dir,offset);
2161         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2162
2163       } else
2164             sprintf(d,"%s",aop->aopu.aop_dir);
2165         
2166         if (strcmp(d,s)) {
2167           DEBUGpic16_emitcode(";","%d",__LINE__);
2168           if(strcmp(s,"W"))
2169             pic16_emitcode("movf","%s,w",s);
2170           pic16_emitcode("movwf","%s",d);
2171
2172           if(strcmp(s,"W")) {
2173             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2174             if(offset >= aop->size) {
2175               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2176               break;
2177             } else
2178               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2179           }
2180
2181           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2182
2183
2184         }
2185         break;
2186         
2187     case AOP_REG:
2188       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2189         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2190           /*
2191             if (*s == '@'           ||
2192                 strcmp(s,"r0") == 0 ||
2193                 strcmp(s,"r1") == 0 ||
2194                 strcmp(s,"r2") == 0 ||
2195                 strcmp(s,"r3") == 0 ||
2196                 strcmp(s,"r4") == 0 ||
2197                 strcmp(s,"r5") == 0 ||
2198                 strcmp(s,"r6") == 0 || 
2199                 strcmp(s,"r7") == 0 )
2200                 pic16_emitcode("mov","%s,%s  ; %d",
2201                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2202             else
2203           */
2204
2205           if(strcmp(s,"W")==0 )
2206             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2207
2208           pic16_emitcode("movwf","%s",
2209                    aop->aopu.aop_reg[offset]->name);
2210
2211           if(strcmp(s,zero)==0) {
2212             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2213
2214           } else if(strcmp(s,"W")==0) {
2215             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2216             pcop->type = PO_GPR_REGISTER;
2217
2218             PCOR(pcop)->rIdx = -1;
2219             PCOR(pcop)->r = NULL;
2220
2221             DEBUGpic16_emitcode(";","%d",__LINE__);
2222             pcop->name = Safe_strdup(s);
2223             pic16_emitpcode(POC_MOVFW,pcop);
2224             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2225           } else if(strcmp(s,one)==0) {
2226             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2227             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2228           } else {
2229             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2230           }
2231         }
2232         break;
2233         
2234     case AOP_DPTR:
2235     case AOP_DPTR2:
2236     
2237     if (aop->type == AOP_DPTR2)
2238     {
2239         genSetDPTR(1);
2240     }
2241     
2242         if (aop->code) {
2243             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2244                    "pic16_aopPut writting to code space");
2245             exit(0);
2246         }
2247         
2248         while (offset > aop->coff) {
2249             aop->coff++;
2250             pic16_emitcode ("inc","dptr");
2251         }
2252         
2253         while (offset < aop->coff) {
2254             aop->coff-- ;
2255             pic16_emitcode("lcall","__decdptr");
2256         }
2257         
2258         aop->coff = offset;
2259         
2260         /* if not in accumulater */
2261         MOVA(s);        
2262         
2263         pic16_emitcode ("movx","@dptr,a");
2264         
2265     if (aop->type == AOP_DPTR2)
2266     {
2267         genSetDPTR(0);
2268     }
2269         break;
2270         
2271     case AOP_R0:
2272     case AOP_R1:
2273         while (offset > aop->coff) {
2274             aop->coff++;
2275             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2276         }
2277         while (offset < aop->coff) {
2278             aop->coff-- ;
2279             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2280         }
2281         aop->coff = offset;
2282         
2283         if (aop->paged) {
2284             MOVA(s);           
2285             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2286             
2287         } else
2288             if (*s == '@') {
2289                 MOVA(s);
2290                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2291             } else
2292                 if (strcmp(s,"r0") == 0 ||
2293                     strcmp(s,"r1") == 0 ||
2294                     strcmp(s,"r2") == 0 ||
2295                     strcmp(s,"r3") == 0 ||
2296                     strcmp(s,"r4") == 0 ||
2297                     strcmp(s,"r5") == 0 ||
2298                     strcmp(s,"r6") == 0 || 
2299                     strcmp(s,"r7") == 0 ) {
2300                     char buffer[10];
2301                     sprintf(buffer,"a%s",s);
2302                     pic16_emitcode("mov","@%s,%s",
2303                              aop->aopu.aop_ptr->name,buffer);
2304                 } else
2305                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2306         
2307         break;
2308         
2309     case AOP_STK:
2310         if (strcmp(s,"a") == 0)
2311             pic16_emitcode("push","acc");
2312         else
2313             pic16_emitcode("push","%s",s);
2314         
2315         break;
2316         
2317     case AOP_CRY:
2318         /* if bit variable */
2319         if (!aop->aopu.aop_dir) {
2320             pic16_emitcode("clr","a");
2321             pic16_emitcode("rlc","a");
2322         } else {
2323             if (s == zero) 
2324                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2325             else
2326                 if (s == one)
2327                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2328                 else
2329                     if (!strcmp(s,"c"))
2330                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2331                     else {
2332                         lbl = newiTempLabel(NULL);
2333                         
2334                         if (strcmp(s,"a")) {
2335                             MOVA(s);
2336                         }
2337                         pic16_emitcode("clr","c");
2338                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2339                         pic16_emitcode("cpl","c");
2340                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2341                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2342                     }
2343         }
2344         break;
2345         
2346     case AOP_STR:
2347         aop->coff = offset;
2348         if (strcmp(aop->aopu.aop_str[offset],s))
2349             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2350         break;
2351         
2352     case AOP_ACC:
2353         aop->coff = offset;
2354         if (!offset && (strcmp(s,"acc") == 0))
2355             break;
2356         
2357         if (strcmp(aop->aopu.aop_str[offset],s))
2358             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2359         break;
2360
2361     default :
2362         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2363 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2364 //             "pic16_aopPut got unsupported aop->type");
2365 //      exit(0);    
2366     }    
2367
2368 }
2369
2370 /*-----------------------------------------------------------------*/
2371 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2372 /*-----------------------------------------------------------------*/
2373 void pic16_mov2w (asmop *aop, int offset)
2374 {
2375   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2376
2377   if(is_LitAOp(aop))
2378     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2379   else
2380     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2381 }
2382
2383 static void mov2f(asmop *dst, asmop *src, int offset)
2384 {
2385   if(is_LitAOp(src)) {
2386     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2387     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2388   } else {
2389     if(pic16_sameRegsOfs(src, dst, offset))return;
2390     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2391                       pic16_popGet(dst, offset)));
2392   }
2393 }
2394
2395 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2396 {
2397   if(is_LitAOp(src)) {
2398     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2399     pic16_emitpcode(POC_MOVWF, dst);
2400   } else {
2401     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2402   }
2403 }
2404
2405 void pic16_testStackOverflow(void)
2406 {
2407 #define GSTACK_TEST_NAME        "_gstack_test"
2408
2409   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2410   
2411   {
2412     symbol *sym;
2413
2414       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2415       sprintf(sym->rname, "%s%s", port->fun_prefix, GSTACK_TEST_NAME);
2416 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2417       checkAddSym(&externs, sym);
2418   }
2419
2420 }
2421
2422 /* push pcop into stack */
2423 void pic16_pushpCodeOp(pCodeOp *pcop)
2424 {
2425 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2426   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));    //&pic16_pc_postdec1)));
2427   if(pic16_options.gstack)
2428     pic16_testStackOverflow();
2429     
2430 }
2431
2432 /* pop pcop from stack */
2433 void pic16_poppCodeOp(pCodeOp *pcop)
2434 {
2435   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2436   if(pic16_options.gstack)
2437     pic16_testStackOverflow();
2438 }
2439
2440
2441 /*-----------------------------------------------------------------*/
2442 /* pushw - pushes wreg to stack                                    */
2443 /*-----------------------------------------------------------------*/
2444 void pushw(void)
2445 {
2446   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2447   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2448   if(pic16_options.gstack)
2449     pic16_testStackOverflow();
2450 }
2451
2452                 
2453 /*-----------------------------------------------------------------*/
2454 /* pushaop - pushes aop to stack                                   */
2455 /*-----------------------------------------------------------------*/
2456 void pushaop(asmop *aop, int offset)
2457 {
2458   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2459
2460   if(is_LitAOp(aop)) {
2461     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2462     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2463   } else {
2464     pic16_emitpcode(POC_MOVFF,
2465       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2466   }
2467
2468   if(pic16_options.gstack)
2469     pic16_testStackOverflow();
2470 }
2471
2472 /*-----------------------------------------------------------------*/
2473 /* popaop - pops aop from stack                                    */
2474 /*-----------------------------------------------------------------*/
2475 void popaop(asmop *aop, int offset)
2476 {
2477   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2478   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2479   if(pic16_options.gstack)
2480     pic16_testStackOverflow();
2481 }
2482
2483 void popaopidx(asmop *aop, int offset, int index)
2484 {
2485   int ofs=1;
2486
2487     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2488
2489     if(STACK_MODEL_LARGE)ofs++;
2490
2491     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2492     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2493     if(pic16_options.gstack)
2494       pic16_testStackOverflow();
2495 }
2496
2497 #if !(USE_GENERIC_SIGNED_SHIFT)
2498 /*-----------------------------------------------------------------*/
2499 /* reAdjustPreg - points a register back to where it should        */
2500 /*-----------------------------------------------------------------*/
2501 static void reAdjustPreg (asmop *aop)
2502 {
2503     int size ;
2504
2505     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2506     aop->coff = 0;
2507     if ((size = aop->size) <= 1)
2508         return ;
2509     size-- ;
2510     switch (aop->type) {
2511         case AOP_R0 :
2512         case AOP_R1 :
2513             while (size--)
2514                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2515             break;          
2516         case AOP_DPTR :
2517         case AOP_DPTR2:
2518             if (aop->type == AOP_DPTR2)
2519             {
2520                 genSetDPTR(1);
2521             } 
2522             while (size--)
2523             {
2524                 pic16_emitcode("lcall","__decdptr");
2525             }
2526                 
2527             if (aop->type == AOP_DPTR2)
2528             {
2529                 genSetDPTR(0);
2530             }                
2531             break;  
2532
2533     }   
2534
2535 }
2536 #endif
2537
2538 #if 0
2539 /*-----------------------------------------------------------------*/
2540 /* opIsGptr: returns non-zero if the passed operand is             */   
2541 /* a generic pointer type.                                         */
2542 /*-----------------------------------------------------------------*/ 
2543 static int opIsGptr(operand *op)
2544 {
2545     sym_link *type = operandType(op);
2546     
2547     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2548     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2549     {
2550         return 1;
2551     }
2552     return 0;        
2553 }
2554 #endif
2555
2556 /*-----------------------------------------------------------------*/
2557 /* pic16_getDataSize - get the operand data size                         */
2558 /*-----------------------------------------------------------------*/
2559 int pic16_getDataSize(operand *op)
2560 {
2561     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2562
2563
2564     return AOP_SIZE(op);
2565
2566     // tsd- in the pic port, the genptr size is 1, so this code here
2567     // fails. ( in the 8051 port, the size was 4).
2568 #if 0
2569     int size;
2570     size = AOP_SIZE(op);
2571     if (size == GPTRSIZE)
2572     {
2573         sym_link *type = operandType(op);
2574         if (IS_GENPTR(type))
2575         {
2576             /* generic pointer; arithmetic operations
2577              * should ignore the high byte (pointer type).
2578              */
2579             size--;
2580     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2581         }
2582     }
2583     return size;
2584 #endif
2585 }
2586
2587 /*-----------------------------------------------------------------*/
2588 /* pic16_outAcc - output Acc                                             */
2589 /*-----------------------------------------------------------------*/
2590 void pic16_outAcc(operand *result)
2591 {
2592   int size,offset;
2593   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2594   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2595
2596
2597   size = pic16_getDataSize(result);
2598   if(size){
2599     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2600     size--;
2601     offset = 1;
2602     /* unsigned or positive */
2603     while(size--)
2604       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2605   }
2606
2607 }
2608
2609 /*-----------------------------------------------------------------*/
2610 /* pic16_outBitC - output a bit C                                  */
2611 /*                 Move to result the value of Carry flag -- VR    */
2612 /*-----------------------------------------------------------------*/
2613 void pic16_outBitC(operand *result)
2614 {
2615   int i;
2616
2617     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2618
2619     /* if the result is bit */
2620     if (AOP_TYPE(result) == AOP_CRY) {
2621         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2622         pic16_aopPut(AOP(result),"c",0);
2623     } else {
2624
2625         i = AOP_SIZE(result);
2626         while(i--) {
2627                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2628         }
2629         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2630     }
2631 }
2632
2633 /*-----------------------------------------------------------------*/
2634 /* pic16_outBitOp - output a bit from Op                           */
2635 /*                 Move to result the value of set/clr op -- VR    */
2636 /*-----------------------------------------------------------------*/
2637 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2638 {
2639   int i;
2640
2641     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2642
2643     /* if the result is bit */
2644     if (AOP_TYPE(result) == AOP_CRY) {
2645         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2646         pic16_aopPut(AOP(result),"c",0);
2647     } else {
2648
2649         i = AOP_SIZE(result);
2650         while(i--) {
2651                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2652         }
2653         pic16_emitpcode(POC_RRCF, pcop);          
2654         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2655     }
2656 }
2657
2658 /*-----------------------------------------------------------------*/
2659 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2660 /*-----------------------------------------------------------------*/
2661 void pic16_toBoolean(operand *oper)
2662 {
2663     int size = AOP_SIZE(oper) - 1;
2664     int offset = 1;
2665
2666     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2667
2668     if ( AOP_TYPE(oper) != AOP_ACC) {
2669       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2670     }
2671     while (size--) {
2672       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2673     }
2674 }
2675
2676
2677 #if !defined(GEN_Not)
2678 /*-----------------------------------------------------------------*/
2679 /* genNot - generate code for ! operation                          */
2680 /*-----------------------------------------------------------------*/
2681 static void pic16_genNot (iCode *ic)
2682 {
2683   symbol *tlbl;
2684   int size;
2685
2686   FENTRY;
2687   /* assign asmOps to operand & result */
2688   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2689   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2690
2691   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2692   /* if in bit space then a special case */
2693   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2694     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2695       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2696       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2697     } else {
2698       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2699       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2700       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2701     }
2702     goto release;
2703   }
2704
2705   size = AOP_SIZE(IC_LEFT(ic));
2706   if(size == 1) {
2707     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2708     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2709     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2710     goto release;
2711   }
2712   pic16_toBoolean(IC_LEFT(ic));
2713
2714   tlbl = newiTempLabel(NULL);
2715   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2716   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2717   pic16_outBitC(IC_RESULT(ic));
2718
2719  release:    
2720   /* release the aops */
2721   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2722   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2723 }
2724 #endif
2725
2726
2727 #if !defined(GEN_Cpl)
2728 /*-----------------------------------------------------------------*/
2729 /* genCpl - generate code for complement                           */
2730 /*-----------------------------------------------------------------*/
2731 static void pic16_genCpl (iCode *ic)
2732 {
2733   int offset = 0;
2734   int size ;
2735
2736     FENTRY;
2737     /* assign asmOps to operand & result */
2738     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2739     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2740
2741     /* if both are in bit space then 
2742     a special case */
2743     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2744         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2745
2746         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2747         pic16_emitcode("cpl","c"); 
2748         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2749         goto release; 
2750     } 
2751
2752     size = AOP_SIZE(IC_RESULT(ic));
2753     while (size--) {
2754 /*
2755         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2756         MOVA(l);       
2757         pic16_emitcode("cpl","a");
2758         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2759 */
2760         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2761               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2762         } else {
2763                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2764                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2765         }
2766         offset++;
2767
2768     }
2769
2770
2771 release:
2772     /* release the aops */
2773     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2774     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2775 }
2776 #endif
2777
2778 /*-----------------------------------------------------------------*/
2779 /* genUminusFloat - unary minus for floating points                */
2780 /*-----------------------------------------------------------------*/
2781 static void genUminusFloat(operand *op,operand *result)
2782 {
2783   int size ,offset =0 ;
2784   
2785     FENTRY;
2786     /* for this we just need to flip the 
2787     first it then copy the rest in place */
2788     size = AOP_SIZE(op);
2789
2790     while(size--) {
2791       mov2f(AOP(result), AOP(op), offset);
2792       offset++;
2793     }
2794     
2795     /* toggle the MSB's highest bit */
2796     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2797 }
2798
2799 /*-----------------------------------------------------------------*/
2800 /* genUminus - unary minus code generation                         */
2801 /*-----------------------------------------------------------------*/
2802 static void genUminus (iCode *ic)
2803 {
2804   int size, i;
2805   sym_link *optype, *rtype;
2806   symbol *label;
2807   int needLabel=0;
2808
2809     FENTRY;     
2810     
2811     /* assign asmops */
2812     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2813     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2814
2815     /* if both in bit space then special case */
2816     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2817       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2818         
2819         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2820         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2821         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2822         goto release; 
2823     } 
2824
2825     optype = operandType(IC_LEFT(ic));
2826     rtype = operandType(IC_RESULT(ic));
2827
2828     /* if float then do float stuff */
2829     if (IS_FLOAT(optype)) {
2830       genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2831       goto release;
2832     }
2833
2834     /* otherwise subtract from zero by taking the 2's complement */
2835     size = AOP_SIZE(IC_LEFT(ic));
2836     label = newiTempLabel ( NULL );
2837     
2838     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2839       for (i=size-1; i > 0; i--) {
2840         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2841       } // for
2842       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2843       for (i=1; i < size; i++) {
2844         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2845         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2846       } // for
2847     } else {
2848       for (i=size-1; i >= 0; i--) {
2849         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2850         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2851       } // for
2852       if (size > 1) {
2853         for (i=0; i < size-2; i++) {
2854           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2855           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2856         } // for
2857         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2858       } // if
2859       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2860     }
2861     if (needLabel)
2862       pic16_emitpLabel (label->key);
2863
2864 release:
2865     /* release the aops */
2866     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2867     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2868 }
2869
2870 #if 0
2871 /*-----------------------------------------------------------------*/
2872 /* saveRegisters - will look for a call and save the registers     */
2873 /*-----------------------------------------------------------------*/
2874 static void saveRegisters(iCode *lic) 
2875 {
2876     int i;
2877     iCode *ic;
2878     bitVect *rsave;
2879     sym_link *dtype;
2880
2881     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2882     /* look for call */
2883     for (ic = lic ; ic ; ic = ic->next) 
2884         if (ic->op == CALL || ic->op == PCALL)
2885             break;
2886
2887     if (!ic) {
2888         fprintf(stderr,"found parameter push with no function call\n");
2889         return ;
2890     }
2891
2892     /* if the registers have been saved already then
2893     do nothing */
2894     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2895         return ;
2896
2897     /* find the registers in use at this time 
2898     and push them away to safety */
2899     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2900                           ic->rUsed);
2901
2902     ic->regsSaved = 1;
2903     if (options.useXstack) {
2904         if (bitVectBitValue(rsave,R0_IDX))
2905             pic16_emitcode("mov","b,r0");
2906         pic16_emitcode("mov","r0,%s",spname);
2907         for (i = 0 ; i < pic16_nRegs ; i++) {
2908             if (bitVectBitValue(rsave,i)) {
2909                 if (i == R0_IDX)
2910                     pic16_emitcode("mov","a,b");
2911                 else
2912                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2913                 pic16_emitcode("movx","@r0,a");
2914                 pic16_emitcode("inc","r0");
2915             }
2916         }
2917         pic16_emitcode("mov","%s,r0",spname);
2918         if (bitVectBitValue(rsave,R0_IDX))
2919             pic16_emitcode("mov","r0,b");           
2920     }// else
2921     //for (i = 0 ; i < pic16_nRegs ; i++) {
2922     //    if (bitVectBitValue(rsave,i))
2923     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2924     //}
2925
2926     dtype = operandType(IC_LEFT(ic));
2927     if (currFunc && dtype && 
2928         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2929         IFFUNC_ISISR(currFunc->type) &&
2930         !ic->bankSaved) 
2931
2932         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2933
2934 }
2935 /*-----------------------------------------------------------------*/
2936 /* unsaveRegisters - pop the pushed registers                      */
2937 /*-----------------------------------------------------------------*/
2938 static void unsaveRegisters (iCode *ic)
2939 {
2940     int i;
2941     bitVect *rsave;
2942
2943     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2944     /* find the registers in use at this time 
2945     and push them away to safety */
2946     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2947                           ic->rUsed);
2948     
2949     if (options.useXstack) {
2950         pic16_emitcode("mov","r0,%s",spname);   
2951         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2952             if (bitVectBitValue(rsave,i)) {
2953                 pic16_emitcode("dec","r0");
2954                 pic16_emitcode("movx","a,@r0");
2955                 if (i == R0_IDX)
2956                     pic16_emitcode("mov","b,a");
2957                 else
2958                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2959             }       
2960
2961         }
2962         pic16_emitcode("mov","%s,r0",spname);
2963         if (bitVectBitValue(rsave,R0_IDX))
2964             pic16_emitcode("mov","r0,b");
2965     } //else
2966     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2967     //    if (bitVectBitValue(rsave,i))
2968     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2969     //}
2970
2971 }  
2972 #endif
2973
2974 #if 0  // patch 14
2975 /*-----------------------------------------------------------------*/
2976 /* pushSide -                                                      */
2977 /*-----------------------------------------------------------------*/
2978 static void pushSide(operand * oper, int size)
2979 {
2980         int offset = 0;
2981     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2982         while (size--) {
2983                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2984                 if (AOP_TYPE(oper) != AOP_REG &&
2985                     AOP_TYPE(oper) != AOP_DIR &&
2986                     strcmp(l,"a") ) {
2987                         pic16_emitcode("mov","a,%s",l);
2988                         pic16_emitcode("push","acc");
2989                 } else
2990                         pic16_emitcode("push","%s",l);
2991         }
2992 }
2993 #endif // patch 14
2994
2995 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2996 {
2997   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2998     pic16_emitpcode(POC_MOVFW, src);
2999     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
3000   } else {
3001     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3002         src, pic16_popGet(AOP(op), offset)));
3003   }
3004 }
3005
3006
3007 /*-----------------------------------------------------------------*/
3008 /* assignResultValue - assign results to oper, rescall==1 is       */
3009 /*                     called from genCall() or genPcall()         */
3010 /*-----------------------------------------------------------------*/
3011 static void assignResultValue(operand * oper, int rescall)
3012 {
3013   int size = AOP_SIZE(oper);
3014   int offset=0;
3015   
3016     FENTRY2;
3017 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3018     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3019
3020     if(rescall) {
3021       /* assign result from a call/pcall function() */
3022                 
3023       /* function results are stored in a special order,
3024        * see top of file with Function return policy, or manual */
3025
3026       if(size <= 4) {
3027         /* 8-bits, result in WREG */
3028         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3029                         
3030         if(size>1) {
3031           /* 16-bits, result in PRODL:WREG */
3032           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3033         }
3034                         
3035         if(size>2) {
3036           /* 24-bits, result in PRODH:PRODL:WREG */
3037           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3038         }
3039                         
3040         if(size>3) {
3041           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3042           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3043         }
3044       
3045       } else {
3046         /* >32-bits, result on stack, and FSR0 points to beginning.
3047          * Fix stack when done */
3048         /* FIXME FIXME */
3049 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3050         while (size--) {
3051 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3052 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3053                 
3054           popaopidx(AOP(oper), size, GpsuedoStkPtr);
3055           GpsuedoStkPtr++;
3056         }
3057                         
3058         /* fix stack */
3059         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3060         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3061         if(STACK_MODEL_LARGE) {
3062           emitSKPNC;
3063           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3064         }
3065       }                 
3066     } else {
3067       int areg = 0;             /* matching argument register */
3068       
3069 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3070       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3071
3072
3073       /* its called from genReceive (probably) -- VR */
3074       /* I hope this code will not be called from somewhere else in the future! 
3075        * We manually set the pseudo stack pointer in genReceive. - dw
3076        */
3077       if(!GpsuedoStkPtr && _G.useWreg) {
3078 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3079
3080         /* The last byte in the assignment is in W */
3081         if(areg <= GpsuedoStkPtr) {
3082           size--;
3083           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3084           offset++;
3085 //          debugf("receive from WREG\n", 0);
3086         }
3087         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3088       }
3089 //      GpsuedoStkPtr++;
3090       _G.stack_lat = AOP_SIZE(oper)-1;
3091
3092       while (size) {
3093         size--;
3094         GpsuedoStkPtr++;
3095         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3096 //        debugf("receive from STACK\n", 0);
3097         offset++;
3098       }
3099     }
3100 }
3101
3102
3103 /*-----------------------------------------------------------------*/
3104 /* genIpush - generate code for pushing this gets a little complex */
3105 /*-----------------------------------------------------------------*/
3106 static void genIpush (iCode *ic)
3107 {
3108 //  int size, offset=0;
3109
3110   FENTRY;
3111   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3112
3113   if(ic->parmPush) {
3114     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3115
3116     /* send to stack as normal */
3117     addSet(&_G.sendSet,ic);
3118 //    addSetHead(&_G.sendSet,ic);
3119     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3120   }
3121
3122         
3123 #if 0
3124     int size, offset = 0 ;
3125     char *l;
3126
3127
3128     /* if this is not a parm push : ie. it is spill push 
3129     and spill push is always done on the local stack */
3130     if (!ic->parmPush) {
3131
3132         /* and the item is spilt then do nothing */
3133         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3134             return ;
3135
3136         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3137         size = AOP_SIZE(IC_LEFT(ic));
3138         /* push it on the stack */
3139         while(size--) {
3140             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3141             if (*l == '#') {
3142                 MOVA(l);
3143                 l = "acc";
3144             }
3145             pic16_emitcode("push","%s",l);
3146         }
3147         return ;        
3148     }
3149
3150     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3151 #endif
3152 }
3153
3154 /*-----------------------------------------------------------------*/
3155 /* genIpop - recover the registers: can happen only for spilling   */
3156 /*-----------------------------------------------------------------*/
3157 static void genIpop (iCode *ic)
3158 {
3159   FENTRY;
3160   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3161 #if 0
3162     int size,offset ;
3163
3164
3165     /* if the temp was not pushed then */
3166     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3167         return ;
3168
3169     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3170     size = AOP_SIZE(IC_LEFT(ic));
3171     offset = (size-1);
3172     while (size--) 
3173         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3174                                    FALSE,TRUE));
3175
3176     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3177 #endif
3178 }
3179
3180 #if 0
3181 /*-----------------------------------------------------------------*/
3182 /* unsaverbank - restores the resgister bank from stack            */
3183 /*-----------------------------------------------------------------*/
3184 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3185 {
3186   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3187 #if 0
3188     int i;
3189     asmop *aop ;
3190     regs *r = NULL;
3191
3192     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3193     if (popPsw) {
3194         if (options.useXstack) {
3195             aop = newAsmop(0);
3196             r = getFreePtr(ic,&aop,FALSE);
3197             
3198             
3199             pic16_emitcode("mov","%s,_spx",r->name);
3200             pic16_emitcode("movx","a,@%s",r->name);
3201             pic16_emitcode("mov","psw,a");
3202             pic16_emitcode("dec","%s",r->name);
3203             
3204         }else
3205             pic16_emitcode ("pop","psw");
3206     }
3207
3208     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3209         if (options.useXstack) {       
3210             pic16_emitcode("movx","a,@%s",r->name);
3211             //pic16_emitcode("mov","(%s+%d),a",
3212             //       regspic16[i].base,8*bank+regspic16[i].offset);
3213             pic16_emitcode("dec","%s",r->name);
3214
3215         } else 
3216           pic16_emitcode("pop",""); //"(%s+%d)",
3217         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3218     }
3219
3220     if (options.useXstack) {
3221
3222         pic16_emitcode("mov","_spx,%s",r->name);
3223         pic16_freeAsmop(NULL,aop,ic,TRUE);
3224
3225     }
3226 #endif 
3227 }
3228
3229 /*-----------------------------------------------------------------*/
3230 /* saverbank - saves an entire register bank on the stack          */
3231 /*-----------------------------------------------------------------*/
3232 static void saverbank (int bank, iCode *ic, bool pushPsw)
3233 {
3234   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3235 #if 0
3236     int i;
3237     asmop *aop ;
3238     regs *r = NULL;
3239
3240     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3241     if (options.useXstack) {
3242
3243         aop = newAsmop(0);
3244         r = getFreePtr(ic,&aop,FALSE);  
3245         pic16_emitcode("mov","%s,_spx",r->name);
3246
3247     }
3248
3249     for (i = 0 ; i < pic16_nRegs ;i++) {
3250         if (options.useXstack) {
3251             pic16_emitcode("inc","%s",r->name);
3252             //pic16_emitcode("mov","a,(%s+%d)",
3253             //         regspic16[i].base,8*bank+regspic16[i].offset);
3254             pic16_emitcode("movx","@%s,a",r->name);           
3255         } else 
3256           pic16_emitcode("push","");// "(%s+%d)",
3257                      //regspic16[i].base,8*bank+regspic16[i].offset);
3258     }
3259     
3260     if (pushPsw) {
3261         if (options.useXstack) {
3262             pic16_emitcode("mov","a,psw");
3263             pic16_emitcode("movx","@%s,a",r->name);     
3264             pic16_emitcode("inc","%s",r->name);
3265             pic16_emitcode("mov","_spx,%s",r->name);       
3266             pic16_freeAsmop (NULL,aop,ic,TRUE);
3267             
3268         } else
3269             pic16_emitcode("push","psw");
3270         
3271         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3272     }
3273     ic->bankSaved = 1;
3274 #endif
3275 }
3276 #endif  /* 0 */
3277
3278
3279 static int wparamCmp(void *p1, void *p2)
3280 {
3281   return (!strcmp((char *)p1, (char *)p2));
3282 }
3283
3284 int inWparamList(char *s)
3285 {
3286   return isinSetWith(wparamList, s, wparamCmp);
3287
3288
3289
3290 /*-----------------------------------------------------------------*/
3291 /* genCall - generates a call statement                            */
3292 /*-----------------------------------------------------------------*/
3293 static void genCall (iCode *ic)
3294 {
3295   sym_link *ftype;   
3296   int stackParms=0;
3297   int use_wreg=0;
3298   int inwparam=0;
3299   char *fname;
3300   
3301     FENTRY;
3302
3303     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3304     /* if caller saves & we have not saved then */
3305 //    if (!ic->regsSaved)
3306 //      saveRegisters(ic);
3307
3308         /* initialise stackParms for IPUSH pushes */
3309 //      stackParms = psuedoStkPtr;
3310 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3311     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3312     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3313
3314 #if 0
3315     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3316 #endif
3317
3318     /* if send set is not empty the assign */
3319     if (_G.sendSet) {
3320       iCode *sic;
3321       int psuedoStkPtr=-1; 
3322       int firstTimeThruLoop = 1;
3323
3324
3325         /* reverse sendSet if function is not reentrant */
3326         if(!IFFUNC_ISREENT(ftype))
3327           _G.sendSet = reverseSet(_G.sendSet);
3328
3329         /* First figure how many parameters are getting passed */
3330         stackParms = 0;
3331         use_wreg = 0;
3332         
3333         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3334           int size;
3335 //          int offset = 0;
3336
3337             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3338             size = AOP_SIZE(IC_LEFT(sic));
3339
3340             stackParms += size;
3341
3342             /* pass the last byte through WREG */
3343             if(inwparam) {
3344
3345               while (size--) {
3346                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3347                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3348                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3349
3350                 if(!firstTimeThruLoop) {
3351                   /* If this is not the first time we've been through the loop
3352                    * then we need to save the parameter in a temporary
3353                    * register. The last byte of the last parameter is
3354                    * passed in W. */
3355
3356                   pushw();
3357 //                  --psuedoStkPtr;             // sanity check
3358                   use_wreg = 1;
3359                 }
3360                 
3361                 firstTimeThruLoop=0;
3362
3363                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3364
3365 //                offset++;
3366               }
3367             } else {
3368               /* all arguments are passed via stack */
3369               use_wreg = 0;
3370
3371               while (size--) {
3372                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3373                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3374                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3375
3376 //                pushaop(AOP(IC_LEFT(sic)), size);
3377                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3378
3379                 if(!_G.resDirect)
3380                   pushw();
3381               }
3382             }
3383
3384             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3385           }
3386
3387           if(inwparam) {
3388             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3389               pushw();  /* save last parameter to stack if functions has varargs */
3390               use_wreg = 0;
3391             } else
3392               use_wreg = 1;
3393           } else use_wreg = 0;
3394
3395           _G.stackRegSet = _G.sendSet;
3396           _G.sendSet = NULL;
3397     }
3398
3399     /* make the call */
3400     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3401
3402     GpsuedoStkPtr=0;
3403     
3404     /* if we need to assign a result value */
3405     if ((IS_ITEMP(IC_RESULT(ic))
3406           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3407               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3408         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3409
3410       _G.accInUse++;
3411       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3412       _G.accInUse--;
3413
3414       assignResultValue(IC_RESULT(ic), 1);
3415
3416       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3417                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3418                 
3419       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3420     }
3421
3422     if(!stackParms && ic->parmBytes) {
3423       stackParms = ic->parmBytes;
3424     }
3425       
3426     stackParms -= use_wreg;
3427     
3428     if(stackParms>0) {
3429       if(stackParms == 1) {
3430         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3431       } else {
3432         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3433         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3434       }
3435       if(STACK_MODEL_LARGE) {
3436         emitSKPNC;
3437         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3438       }
3439     }
3440
3441 #if 0
3442     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3443 #endif
3444
3445     /* adjust the stack for parameters if required */
3446 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3447
3448 #if 0
3449       /* if register bank was saved then pop them */
3450       if (ic->bankSaved)
3451         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3452
3453       /* if we hade saved some registers then unsave them */
3454       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3455         unsaveRegisters (ic);
3456 #endif
3457 }
3458
3459
3460
3461 /*-----------------------------------------------------------------*/
3462 /* genPcall - generates a call by pointer statement                */
3463 /*            new version, created from genCall - HJD              */
3464 /*-----------------------------------------------------------------*/
3465 static void genPcall (iCode *ic)
3466 {
3467   sym_link *ftype, *fntype;
3468   int stackParms=0;
3469   symbol *retlbl = newiTempLabel(NULL);
3470   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3471   
3472     FENTRY;
3473
3474     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3475     fntype = operandType( IC_LEFT(ic) )->next;
3476
3477     /* if send set is not empty the assign */
3478     if (_G.sendSet) {
3479       iCode *sic;
3480       int psuedoStkPtr=-1; 
3481
3482       /* reverse sendSet if function is not reentrant */
3483       if(!IFFUNC_ISREENT(fntype))
3484         _G.sendSet = reverseSet(_G.sendSet);
3485
3486       stackParms = 0;
3487       
3488       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3489         int size;
3490
3491           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3492           size = AOP_SIZE(IC_LEFT(sic));
3493           stackParms += size;
3494
3495           /* all parameters are passed via stack, since WREG is clobbered
3496            * by the calling sequence */
3497           while (size--) {
3498             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3499             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3500             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3501
3502             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3503             pushw();
3504           }
3505
3506           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3507       }
3508
3509       _G.stackRegSet = _G.sendSet;
3510       _G.sendSet = NULL;
3511     }
3512
3513     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3514
3515     // push return address
3516     // push $ on return stack, then replace with retlbl
3517
3518     /* Thanks to Thorsten Klose for pointing out that the following
3519      * snippet should be interrupt safe */
3520     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3521     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3522
3523     pic16_emitpcodeNULLop(POC_PUSH);
3524
3525     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3526     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3527     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3528     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3529     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3530     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3531
3532
3533     /* restore interrupt control register */
3534     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3535     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3536
3537     /* make the call by writing the pointer into pc */
3538     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3539     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3540
3541     // note: MOVFF to PCL not allowed
3542     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3543     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3544
3545
3546     /* return address is here: (X) */
3547     pic16_emitpLabelFORCE(retlbl->key);
3548
3549     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3550
3551     GpsuedoStkPtr=0;
3552     /* if we need assign a result value */
3553     if ((IS_ITEMP(IC_RESULT(ic))
3554           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3555               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3556         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3557
3558       _G.accInUse++;
3559       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3560       _G.accInUse--;
3561
3562       assignResultValue(IC_RESULT(ic), 1);
3563
3564       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3565               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3566                 
3567       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3568     }
3569
3570 //    stackParms -= use_wreg;
3571     
3572     if(stackParms>0) {
3573       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3574       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3575       if(STACK_MODEL_LARGE) {
3576         emitSKPNC;
3577         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3578       }
3579     }
3580 }
3581
3582 /*-----------------------------------------------------------------*/
3583 /* resultRemat - result  is rematerializable                       */
3584 /*-----------------------------------------------------------------*/
3585 static int resultRemat (iCode *ic)
3586 {
3587   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3588   if (SKIP_IC(ic) || ic->op == IFX)
3589     return 0;
3590
3591   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3592     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3593     if (sym->remat && !POINTER_SET(ic)) 
3594       return 1;
3595   }
3596
3597   return 0;
3598 }
3599
3600 #if defined(__BORLANDC__) || defined(_MSC_VER)
3601 #define STRCASECMP stricmp
3602 #else
3603 #define STRCASECMP strcasecmp
3604 #endif
3605
3606 #if 0
3607 /*-----------------------------------------------------------------*/
3608 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3609 /*-----------------------------------------------------------------*/
3610 static bool inExcludeList(char *s)
3611 {
3612   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3613     int i =0;
3614     
3615     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3616     if (options.excludeRegs[i] &&
3617     STRCASECMP(options.excludeRegs[i],"none") == 0)
3618         return FALSE ;
3619
3620     for ( i = 0 ; options.excludeRegs[i]; i++) {
3621         if (options.excludeRegs[i] &&
3622         STRCASECMP(s,options.excludeRegs[i]) == 0)
3623             return TRUE;
3624     }
3625     return FALSE ;
3626 }
3627 #endif
3628
3629 /*-----------------------------------------------------------------*/
3630 /* genFunction - generated code for function entry                 */
3631 /*-----------------------------------------------------------------*/
3632 static void genFunction (iCode *ic)
3633 {
3634   symbol *sym;
3635   sym_link *ftype;
3636   
3637     FENTRY;
3638     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3639
3640     pic16_labelOffset += (max_key+4);
3641     max_key=0;
3642     GpsuedoStkPtr=0;
3643     _G.nRegsSaved = 0;
3644         
3645     ftype = operandType(IC_LEFT(ic));
3646     sym = OP_SYMBOL(IC_LEFT(ic));
3647
3648     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3649       /* create an absolute section at the interrupt vector:
3650        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3651       symbol *asym;
3652       char asymname[128];
3653       pBlock *apb;
3654
3655 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3656
3657         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3658           sprintf(asymname, "ivec_%s", sym->name);
3659         else
3660           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3661   
3662         /* when an interrupt is declared as naked, do not emit the special
3663          * wrapper segment at vector address. The user should take care for
3664          * this instead. -- VR */
3665
3666         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) =! INTNO_UNSPEC)) {
3667           asym = newSymbol(asymname, 0);
3668           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3669           pic16_addpBlock( apb );
3670
3671           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3672           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3673           pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3674                 
3675           /* mark the end of this tiny function */
3676           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3677         } else {
3678           sprintf(asymname, "%s", sym->rname);
3679         }
3680
3681         {
3682           absSym *abSym;
3683
3684             abSym = Safe_calloc(1, sizeof(absSym));
3685             strcpy(abSym->name, asymname);
3686
3687             switch( FUNC_INTNO(sym->type) ) {
3688               case 0: abSym->address = 0x000000; break;
3689               case 1: abSym->address = 0x000008; break;
3690               case 2: abSym->address = 0x000018; break;
3691               
3692               default:
3693 //                fprintf(stderr, "no interrupt number is given\n");
3694                 abSym->address = -1; break;
3695             }
3696
3697             /* relocate interrupt vectors if needed */
3698             if(abSym->address != -1)
3699               abSym->address += pic16_options.ivt_loc;
3700
3701             addSet(&absSymSet, abSym);
3702         }
3703     }
3704
3705     /* create the function header */
3706     pic16_emitcode(";","-----------------------------------------");
3707     pic16_emitcode(";"," function %s",sym->name);
3708     pic16_emitcode(";","-----------------------------------------");
3709
3710     pic16_emitcode("","%s:",sym->rname);
3711     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3712
3713     {
3714       absSym *ab;
3715
3716         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3717           if(!strcmp(ab->name, sym->rname)) {
3718             pic16_pBlockConvert2Absolute(pb);
3719             break;
3720           }
3721         }
3722     }
3723
3724     if(IFFUNC_ISNAKED(ftype)) {
3725       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3726       return;
3727     }
3728         
3729     /* if critical function then turn interrupts off */
3730     if (IFFUNC_ISCRITICAL(ftype)) {
3731       //pic16_emitcode("clr","ea");
3732     }
3733
3734     currFunc = sym;             /* update the currFunc symbol */
3735     _G.fregsUsed = sym->regsUsed;
3736     _G.sregsAlloc = newBitVect(128);
3737     
3738
3739     /* if this is an interrupt service routine then
3740      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3741     if (IFFUNC_ISISR(sym->type)) {
3742         _G.usefastretfie = 1;   /* use shadow registers by default */
3743         
3744         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3745         if(!FUNC_ISSHADOWREGS(sym->type)) {
3746           /* do not save WREG,STATUS,BSR for high priority interrupts
3747            * because they are stored in the hardware shadow registers already */
3748           _G.usefastretfie = 0;
3749           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3750           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3751           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3752         }
3753
3754         /* these should really be optimized somehow, because not all
3755          * interrupt handlers modify them */
3756         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3757         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3758         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3759         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3760         
3761 //        pic16_pBlockConvert2ISR(pb);
3762     }
3763
3764     /* emit code to setup stack frame if user enabled,
3765      * and function is not main() */
3766     
3767 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3768     if(strcmp(sym->name, "main")) {
3769       if(0 
3770         || !options.ommitFramePtr 
3771 //        || sym->regsUsed
3772         || IFFUNC_ARGS(sym->type)
3773         || FUNC_HASSTACKPARM(sym->etype)
3774         ) {
3775         /* setup the stack frame */
3776         if(STACK_MODEL_LARGE)
3777           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3778         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3779
3780         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3781         if(STACK_MODEL_LARGE)
3782           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3783       }
3784     }
3785
3786     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3787           && sym->stack) {
3788
3789       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3790
3791       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3792       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3793       emitSKPC;
3794       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3795     }
3796           
3797     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3798       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3799         _G.useWreg = 0;
3800       else
3801         _G.useWreg = 1;
3802     } else
3803       _G.useWreg = 0;
3804
3805     /* if callee-save to be used for this function
3806      * then save the registers being used in this function */
3807 //    if (IFFUNC_CALLEESAVES(sym->type))
3808     {
3809       int i;
3810
3811         /* if any registers used */
3812         if (sym->regsUsed) {
3813           /* save the registers used */
3814           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3815           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3816           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3817             if (bitVectBitValue(sym->regsUsed,i)) {
3818               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3819               _G.nRegsSaved++;
3820
3821               if(!pic16_regWithIdx(i)->wasUsed) {
3822                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3823                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3824                 pic16_regWithIdx(i)->wasUsed = 1;
3825               }
3826             }
3827           }
3828           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3829         }
3830     }
3831         
3832     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3833 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3834 }
3835
3836 /*-----------------------------------------------------------------*/
3837 /* genEndFunction - generates epilogue for functions               */
3838 /*-----------------------------------------------------------------*/
3839 static void genEndFunction (iCode *ic)
3840 {
3841   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3842
3843     FENTRY;
3844
3845     if(IFFUNC_ISNAKED(sym->type)) {
3846       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3847       return;
3848     }
3849
3850     _G.stack_lat = 0;
3851
3852     /* add code for ISCRITICAL */
3853     if(IFFUNC_ISCRITICAL(sym->type)) {
3854       /* if critical function, turn on interrupts */
3855       
3856       /* TODO: add code here -- VR */
3857     }
3858     
3859 //    sym->regsUsed = _G.fregsUsed;
3860     
3861     /* now we need to restore the registers */
3862     /* if any registers used */
3863
3864     /* first restore registers that might be used for stack access */
3865     if(_G.sregsAllocSet) {
3866     regs *sr;
3867     
3868       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3869       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3870         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3871       }
3872     }
3873
3874     if (sym->regsUsed) {
3875       int i;
3876
3877         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3878         /* restore registers used */
3879         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3880         for ( i = sym->regsUsed->size; i >= 0; i--) {
3881           if (bitVectBitValue(sym->regsUsed,i)) {
3882             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3883             _G.nRegsSaved--;
3884           }
3885         }
3886         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3887     }
3888
3889       
3890
3891     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3892           && sym->stack) {
3893       if (sym->stack == 1) {
3894         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3895         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3896       } else {
3897         // we have to add more than one...
3898         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3899         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3900         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3901         emitSKPNC;
3902         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3903         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3904         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3905       }
3906     }
3907
3908     if(strcmp(sym->name, "main")) {
3909       if(0
3910         || !options.ommitFramePtr
3911 //        || sym->regsUsed
3912         || IFFUNC_ARGS(sym->type)
3913         || FUNC_HASSTACKPARM(sym->etype)
3914         ) {
3915         /* restore stack frame */
3916         if(STACK_MODEL_LARGE)
3917           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3918         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3919       }
3920     }
3921
3922     _G.useWreg = 0;
3923
3924     if (IFFUNC_ISISR(sym->type)) {
3925       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3926       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3927       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3928       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3929
3930       if(!FUNC_ISSHADOWREGS(sym->type)) {
3931         /* do not restore interrupt vector for WREG,STATUS,BSR
3932          * for high priority interrupt, see genFunction */
3933         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3934         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3935         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3936       }
3937 //      _G.interruptvector = 0;         /* sanity check */
3938
3939
3940       /* if debug then send end of function */
3941 /*      if (options.debug && currFunc)  */
3942       if (currFunc) {
3943         debugFile->writeEndFunction (currFunc, ic, 1);
3944       }
3945         
3946       if(_G.usefastretfie)
3947         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3948       else
3949         pic16_emitpcodeNULLop(POC_RETFIE);
3950
3951       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3952       
3953       _G.usefastretfie = 0;
3954       return;
3955     }
3956
3957     if (IFFUNC_ISCRITICAL(sym->type)) {
3958       pic16_emitcode("setb","ea");
3959     }
3960
3961     /* if debug then send end of function */
3962     if (currFunc) {
3963       debugFile->writeEndFunction (currFunc, ic, 1);
3964     }
3965
3966     /* insert code to restore stack frame, if user enabled it
3967      * and function is not main() */
3968          
3969
3970     pic16_emitpcodeNULLop(POC_RETURN);
3971
3972     /* Mark the end of a function */
3973     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3974 }
3975
3976
3977 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3978 {
3979   unsigned long lit=1;
3980   operand *op;
3981
3982     op = IC_LEFT(ic);
3983   
3984     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3985     if(AOP_TYPE(op) == AOP_LIT) {
3986       if(!IS_FLOAT(operandType( op ))) {
3987         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3988       } else {
3989         union {
3990           unsigned long lit_int;
3991           float lit_float;
3992         } info;
3993         
3994         /* take care if literal is a float */
3995         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3996         lit = info.lit_int;
3997       }
3998     }
3999
4000     if(is_LitOp(op)) {
4001       if(/*(OP_LIVETO(op) <= ic->seq) &&*/ (lit == 0)) {
4002         pic16_emitpcode(POC_CLRF, dest);
4003       } else {
4004         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
4005         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
4006       }
4007     } else {
4008       if(dest->type == PO_WREG && (offset == 0)) {
4009         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4010       return;
4011     }
4012     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4013   }
4014 }
4015
4016 /*-----------------------------------------------------------------*/
4017 /* genRet - generate code for return statement                     */
4018 /*-----------------------------------------------------------------*/
4019 static void genRet (iCode *ic)
4020 {
4021   int size;
4022   operand *left;
4023
4024     FENTRY;
4025         /* if we have no return value then
4026          * just generate the "ret" */
4027         
4028         if (!IC_LEFT(ic)) 
4029                 goto jumpret;       
4030     
4031         /* we have something to return then
4032          * move the return value into place */
4033         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4034         size = AOP_SIZE(IC_LEFT(ic));
4035
4036         if(size <= 4) {
4037           if(size>3)
4038             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4039           
4040           if(size>2)
4041             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4042
4043           if(size>1)
4044             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4045           
4046           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4047
4048         } else {
4049                 /* >32-bits, setup stack and FSR0 */
4050                 while (size--) {
4051 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4052 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4053
4054                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4055
4056 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
4057                         GpsuedoStkPtr++;
4058                 }
4059                         
4060                 /* setup FSR0 */
4061                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4062                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4063
4064                 if(STACK_MODEL_LARGE) {
4065                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4066                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4067                 } else {
4068                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4069                 }
4070         }
4071                                 
4072 #if 0
4073         /* old code, left here for reference -- VR */    
4074         while (size--) {
4075           char *l ;
4076
4077                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4078                         /* #NOCHANGE */
4079                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4080                         pic16_emitpcomment("push %s",l);
4081                         pushed++;
4082                 } else {
4083                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4084                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4085                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4086                         
4087                         if (strcmp(fReturn[offset],l)) {
4088                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4089                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4090                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4091                                 } else {
4092                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4093                                 }
4094                                 
4095                                 if(size) {
4096                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4097                                 }
4098                                 offset++;
4099                         }
4100                 }
4101         }    
4102
4103         if (pushed) {
4104                 while(pushed) {
4105                         pushed--;
4106                         if (strcmp(fReturn[pushed],"a"))
4107                                 pic16_emitcode("pop",fReturn[pushed]);
4108                         else
4109                                 pic16_emitcode("pop","acc");
4110                 }
4111         }
4112 #endif
4113
4114
4115         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4116     
4117 jumpret:
4118         /* generate a jump to the return label
4119          * if the next is not the return statement */
4120         if (!(ic->next && ic->next->op == LABEL
4121                 && IC_LABEL(ic->next) == returnLabel)) {
4122         
4123                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4124                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4125         }
4126 }
4127
4128 /*-----------------------------------------------------------------*/
4129 /* genLabel - generates a label                                    */
4130 /*-----------------------------------------------------------------*/
4131 static void genLabel (iCode *ic)
4132 {
4133   FENTRY;
4134
4135   /* special case never generate */
4136   if (IC_LABEL(ic) == entryLabel)
4137     return ;
4138
4139   pic16_emitpLabel(IC_LABEL(ic)->key);
4140 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4141 }
4142
4143 /*-----------------------------------------------------------------*/
4144 /* genGoto - generates a goto                                      */
4145 /*-----------------------------------------------------------------*/
4146 //tsd
4147 static void genGoto (iCode *ic)
4148 {
4149   FENTRY;
4150   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4151 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4152 }
4153
4154
4155 /*-----------------------------------------------------------------*/
4156 /* genMultbits :- multiplication of bits                           */
4157 /*-----------------------------------------------------------------*/
4158 static void genMultbits (operand *left, 
4159                          operand *right, 
4160                          operand *result)
4161 {
4162   FENTRY;
4163
4164   if(!pic16_sameRegs(AOP(result),AOP(right)))
4165     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4166
4167   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4168   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4169   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4170
4171 }
4172
4173
4174 /*-----------------------------------------------------------------*/
4175 /* genMultOneByte : 8 bit multiplication & division                */
4176 /*-----------------------------------------------------------------*/
4177 static void genMultOneByte (operand *left,
4178                             operand *right,
4179                             operand *result)
4180 {
4181
4182   FENTRY;
4183   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4184   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4185
4186   /* (if two literals, the value is computed before) */
4187   /* if one literal, literal on the right */
4188   if (AOP_TYPE(left) == AOP_LIT){
4189     operand *t = right;
4190     right = left;
4191     left = t;
4192   }
4193
4194         /* size is already checked in genMult == 1 */
4195 //      size = AOP_SIZE(result);
4196
4197         if (AOP_TYPE(right) == AOP_LIT){
4198                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4199                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4200                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4201                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4202         } else {
4203                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4204                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4205                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4206                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4207         }
4208         
4209         pic16_genMult8X8_8 (left, right,result);
4210 }
4211
4212 /*-----------------------------------------------------------------*/
4213 /* genMultOneWord : 16 bit multiplication                          */
4214 /*-----------------------------------------------------------------*/
4215 static void genMultOneWord (operand *left,
4216                             operand *right,
4217                             operand *result)
4218 {
4219   FENTRY;
4220   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4221   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4222
4223   /* (if two literals, the value is computed before)
4224    * if one literal, literal on the right */
4225   if (AOP_TYPE(left) == AOP_LIT){
4226     operand *t = right;
4227     right = left;
4228     left = t;
4229   }
4230
4231   /* size is checked already == 2 */
4232 //  size = AOP_SIZE(result);
4233
4234   if (AOP_TYPE(right) == AOP_LIT) {
4235     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4236       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4237       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4238       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4239   } else {
4240     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4241       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4242       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4243       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4244   }
4245         
4246   pic16_genMult16X16_16(left, right,result);
4247 }
4248
4249 /*-----------------------------------------------------------------*/
4250 /* genMultOneLong : 32 bit multiplication                          */
4251 /*-----------------------------------------------------------------*/
4252 static void genMultOneLong (operand *left,
4253                             operand *right,
4254                             operand *result)
4255 {
4256   FENTRY;
4257   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4258   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4259
4260   /* (if two literals, the value is computed before)
4261    * if one literal, literal on the right */
4262   if (AOP_TYPE(left) == AOP_LIT){
4263     operand *t = right;
4264     right = left;
4265     left = t;
4266   }
4267
4268   /* size is checked already == 4 */
4269 //  size = AOP_SIZE(result);
4270
4271   if (AOP_TYPE(right) == AOP_LIT) {
4272     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4273         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4274         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4275         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4276   } else {
4277     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4278         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4279         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4280         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4281   }
4282         
4283   pic16_genMult32X32_32(left, right,result);
4284 }
4285
4286
4287
4288 /*-----------------------------------------------------------------*/
4289 /* genMult - generates code for multiplication                     */
4290 /*-----------------------------------------------------------------*/
4291 static void genMult (iCode *ic)
4292 {
4293   operand *left = IC_LEFT(ic);
4294   operand *right = IC_RIGHT(ic);
4295   operand *result= IC_RESULT(ic);   
4296
4297     FENTRY;
4298         /* assign the amsops */
4299         pic16_aopOp (left,ic,FALSE);
4300         pic16_aopOp (right,ic,FALSE);
4301         pic16_aopOp (result,ic,TRUE);
4302
4303         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4304
4305         /* special cases first *
4306         * both are bits */
4307         if (AOP_TYPE(left) == AOP_CRY
4308                 && AOP_TYPE(right)== AOP_CRY) {
4309                 genMultbits(left,right,result);
4310           goto release ;
4311         }
4312
4313         /* if both are of size == 1 */
4314         if(AOP_SIZE(left) == 1
4315                 && AOP_SIZE(right) == 1) {
4316                 genMultOneByte(left,right,result);
4317           goto release ;
4318         }
4319
4320         /* if both are of size == 2 */
4321         if(AOP_SIZE(left) == 2
4322                 && AOP_SIZE(right) == 2) {
4323                 genMultOneWord(left, right, result);
4324           goto release;
4325         }
4326         
4327         /* if both are of size == 4 */
4328         if(AOP_SIZE(left) == 4
4329                 && AOP_SIZE(right) == 4) {
4330                 genMultOneLong(left, right, result);
4331           goto release;
4332         }
4333         
4334         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4335
4336
4337         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4338         /* should have been converted to function call */
4339         assert(0) ;
4340
4341 release :
4342         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4343         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4344         pic16_freeAsmop(result,NULL,ic,TRUE); 
4345 }
4346
4347 /*-----------------------------------------------------------------*/
4348 /* genDivbits :- division of bits                                  */
4349 /*-----------------------------------------------------------------*/
4350 static void genDivbits (operand *left, 
4351                         operand *right, 
4352                         operand *result)
4353 {
4354   char *l;
4355
4356     FENTRY;
4357     /* the result must be bit */    
4358     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4359     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4360
4361     MOVA(l);    
4362
4363     pic16_emitcode("div","ab");
4364     pic16_emitcode("rrc","a");
4365     pic16_aopPut(AOP(result),"c",0);
4366 }
4367
4368 /*-----------------------------------------------------------------*/
4369 /* genDivOneByte : 8 bit division                                  */
4370 /*-----------------------------------------------------------------*/
4371 static void genDivOneByte (operand *left,
4372                            operand *right,
4373                            operand *result)
4374 {
4375   sym_link *opetype = operandType(result);
4376   char *l ;
4377   symbol *lbl ;
4378   int size,offset;
4379
4380         /* result = divident / divisor
4381          * - divident may be a register or a literal,
4382          * - divisor may be a register or a literal,
4383          * so there are 3 cases (literal / literal is optimized
4384          * by the front-end) to handle.
4385          * In addition we must handle signed and unsigned, which
4386          * result in 6 final different cases -- VR */
4387
4388     FENTRY;
4389     
4390     size = AOP_SIZE(result) - 1;
4391     offset = 1;
4392     /* signed or unsigned */
4393     if (SPEC_USIGN(opetype)) {
4394       pCodeOp *pct1,    /* count */
4395                 *pct2,  /* reste */
4396                 *pct3;  /* temp */
4397       symbol *label1, *label2, *label3;;
4398
4399
4400         /* unsigned is easy */
4401
4402         pct1 = pic16_popGetTempReg(1);
4403         pct2 = pic16_popGetTempReg(1);
4404         pct3 = pic16_popGetTempReg(1);
4405         
4406         label1 = newiTempLabel(NULL);
4407         label2 = newiTempLabel(NULL);
4408         label3 = newiTempLabel(NULL);
4409
4410         /* the following algorithm is extracted from divuint.c */
4411
4412         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4413         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4414         
4415         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4416
4417         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4418         
4419         pic16_emitpLabel(label1->key);
4420         
4421         emitCLRC;
4422         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4423
4424
4425         emitCLRC;
4426         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4427         
4428
4429         emitSKPNC;
4430         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4431         
4432         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4433         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4434         
4435         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4436         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4437         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4438         
4439         pic16_emitpLabel( label3->key );
4440         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4441         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4442         
4443         
4444
4445         pic16_emitpLabel(label2->key);
4446         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4447         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4448         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4449         
4450         /* result is in wreg */
4451         if(AOP_TYPE(result) != AOP_ACC)
4452                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4453
4454         pic16_popReleaseTempReg( pct3, 1);
4455         pic16_popReleaseTempReg( pct2, 1);
4456         pic16_popReleaseTempReg( pct1, 1);
4457
4458         return ;
4459     }
4460
4461     /* signed is a little bit more difficult */
4462
4463     /* save the signs of the operands */
4464     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4465     MOVA(l);    
4466     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4467     pic16_emitcode("push","acc"); /* save it on the stack */
4468
4469     /* now sign adjust for both left & right */
4470     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4471     MOVA(l);       
4472     lbl = newiTempLabel(NULL);
4473     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4474     pic16_emitcode("cpl","a");   
4475     pic16_emitcode("inc","a");
4476     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4477     pic16_emitcode("mov","b,a");
4478
4479     /* sign adjust left side */
4480     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4481     MOVA(l);
4482
4483     lbl = newiTempLabel(NULL);
4484     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4485     pic16_emitcode("cpl","a");
4486     pic16_emitcode("inc","a");
4487     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4488
4489     /* now the division */
4490     pic16_emitcode("div","ab");
4491     /* we are interested in the lower order
4492     only */
4493     pic16_emitcode("mov","b,a");
4494     lbl = newiTempLabel(NULL);
4495     pic16_emitcode("pop","acc");   
4496     /* if there was an over flow we don't 
4497     adjust the sign of the result */
4498     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4499     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4500     CLRC;
4501     pic16_emitcode("clr","a");
4502     pic16_emitcode("subb","a,b");
4503     pic16_emitcode("mov","b,a");
4504     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4505
4506     /* now we are done */
4507     pic16_aopPut(AOP(result),"b",0);
4508     if(size > 0){
4509         pic16_emitcode("mov","c,b.7");
4510         pic16_emitcode("subb","a,acc");   
4511     }
4512     while (size--)
4513         pic16_aopPut(AOP(result),"a",offset++);
4514
4515 }
4516
4517 /*-----------------------------------------------------------------*/
4518 /* genDiv - generates code for division                            */
4519 /*-----------------------------------------------------------------*/
4520 static void genDiv (iCode *ic)
4521 {
4522     operand *left = IC_LEFT(ic);
4523     operand *right = IC_RIGHT(ic);
4524     operand *result= IC_RESULT(ic);   
4525
4526
4527         /* Division is a very lengthy algorithm, so it is better
4528          * to call support routines than inlining algorithm.
4529          * Division functions written here just in case someone
4530          * wants to inline and not use the support libraries -- VR */
4531
4532     FENTRY;
4533     
4534     /* assign the amsops */
4535     pic16_aopOp (left,ic,FALSE);
4536     pic16_aopOp (right,ic,FALSE);
4537     pic16_aopOp (result,ic,TRUE);
4538
4539     /* special cases first */
4540     /* both are bits */
4541     if (AOP_TYPE(left) == AOP_CRY &&
4542         AOP_TYPE(right)== AOP_CRY) {
4543         genDivbits(left,right,result);
4544         goto release ;
4545     }
4546
4547     /* if both are of size == 1 */
4548     if (AOP_SIZE(left) == 1 &&
4549         AOP_SIZE(right) == 1 ) {
4550         genDivOneByte(left,right,result);
4551         goto release ;
4552     }
4553
4554     /* should have been converted to function call */
4555     assert(0);
4556 release :
4557     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4558     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4559     pic16_freeAsmop(result,NULL,ic,TRUE); 
4560 }
4561
4562 /*-----------------------------------------------------------------*/
4563 /* genModbits :- modulus of bits                                   */
4564 /*-----------------------------------------------------------------*/
4565 static void genModbits (operand *left, 
4566                         operand *right, 
4567                         operand *result)
4568 {
4569   char *l;
4570
4571     FENTRY;  
4572     
4573     werror(W_POSSBUG2, __FILE__, __LINE__);
4574     /* the result must be bit */    
4575     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4576     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4577
4578     MOVA(l);       
4579
4580     pic16_emitcode("div","ab");
4581     pic16_emitcode("mov","a,b");
4582     pic16_emitcode("rrc","a");
4583     pic16_aopPut(AOP(result),"c",0);
4584 }
4585
4586 /*-----------------------------------------------------------------*/
4587 /* genModOneByte : 8 bit modulus                                   */
4588 /*-----------------------------------------------------------------*/
4589 static void genModOneByte (operand *left,
4590                            operand *right,
4591                            operand *result)
4592 {
4593   sym_link *opetype = operandType(result);
4594   char *l ;
4595   symbol *lbl ;
4596
4597     FENTRY;
4598     werror(W_POSSBUG2, __FILE__, __LINE__);
4599
4600     /* signed or unsigned */
4601     if (SPEC_USIGN(opetype)) {
4602         /* unsigned is easy */
4603         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4604         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4605         MOVA(l);    
4606         pic16_emitcode("div","ab");
4607         pic16_aopPut(AOP(result),"b",0);
4608         return ;
4609     }
4610
4611     /* signed is a little bit more difficult */
4612
4613     /* save the signs of the operands */
4614     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4615     MOVA(l);
4616
4617     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4618     pic16_emitcode("push","acc"); /* save it on the stack */
4619
4620     /* now sign adjust for both left & right */
4621     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4622     MOVA(l);
4623
4624     lbl = newiTempLabel(NULL);
4625     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4626     pic16_emitcode("cpl","a");   
4627     pic16_emitcode("inc","a");
4628     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4629     pic16_emitcode("mov","b,a"); 
4630
4631     /* sign adjust left side */
4632     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4633     MOVA(l);
4634
4635     lbl = newiTempLabel(NULL);
4636     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4637     pic16_emitcode("cpl","a");   
4638     pic16_emitcode("inc","a");
4639     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4640
4641     /* now the multiplication */
4642     pic16_emitcode("div","ab");
4643     /* we are interested in the lower order
4644     only */
4645     lbl = newiTempLabel(NULL);
4646     pic16_emitcode("pop","acc");   
4647     /* if there was an over flow we don't 
4648     adjust the sign of the result */
4649     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4650     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4651     CLRC ;
4652     pic16_emitcode("clr","a");
4653     pic16_emitcode("subb","a,b");
4654     pic16_emitcode("mov","b,a");
4655     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4656
4657     /* now we are done */
4658     pic16_aopPut(AOP(result),"b",0);
4659
4660 }
4661
4662 /*-----------------------------------------------------------------*/
4663 /* genMod - generates code for division                            */
4664 /*-----------------------------------------------------------------*/
4665 static void genMod (iCode *ic)
4666 {
4667   operand *left = IC_LEFT(ic);
4668   operand *right = IC_RIGHT(ic);
4669   operand *result= IC_RESULT(ic);  
4670
4671     FENTRY;
4672     
4673     /* assign the amsops */
4674     pic16_aopOp (left,ic,FALSE);
4675     pic16_aopOp (right,ic,FALSE);
4676     pic16_aopOp (result,ic,TRUE);
4677
4678     /* special cases first */
4679     /* both are bits */
4680     if (AOP_TYPE(left) == AOP_CRY &&
4681         AOP_TYPE(right)== AOP_CRY) {
4682         genModbits(left,right,result);
4683         goto release ;
4684     }
4685
4686     /* if both are of size == 1 */
4687     if (AOP_SIZE(left) == 1 &&
4688         AOP_SIZE(right) == 1 ) {
4689         genModOneByte(left,right,result);
4690         goto release ;
4691     }
4692
4693     /* should have been converted to function call */
4694     assert(0);
4695
4696 release :
4697     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4698     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4699     pic16_freeAsmop(result,NULL,ic,TRUE); 
4700 }
4701
4702 /*-----------------------------------------------------------------*/
4703 /* genIfxJump :- will create a jump depending on the ifx           */
4704 /*-----------------------------------------------------------------*/
4705 /*
4706   note: May need to add parameter to indicate when a variable is in bit space.
4707 */
4708 static void genIfxJump (iCode *ic, char *jval)
4709 {
4710   FENTRY;
4711   
4712     /* if true label then we jump if condition
4713     supplied is true */
4714     if ( IC_TRUE(ic) ) {
4715
4716         if(strcmp(jval,"a") == 0)
4717           emitSKPZ;
4718         else if (strcmp(jval,"c") == 0)
4719           emitSKPNC;
4720         else {
4721           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4722           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4723         }
4724
4725         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4726         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4727
4728     }
4729     else {
4730         /* false label is present */
4731         if(strcmp(jval,"a") == 0)
4732           emitSKPNZ;
4733         else if (strcmp(jval,"c") == 0)
4734           emitSKPC;
4735         else {
4736           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4737           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4738         }
4739
4740         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4741         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4742
4743     }
4744
4745
4746     /* mark the icode as generated */
4747     ic->generated = 1;
4748 }
4749
4750 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4751 {
4752   FENTRY;
4753   
4754     /* if true label then we jump if condition
4755     supplied is true */
4756     if ( IC_TRUE(ic) ) {
4757       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4758       pic16_emitpcode(POC_BTFSC, jop);
4759
4760       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4761       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4762
4763     } else {
4764       /* false label is present */
4765       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4766       pic16_emitpcode(POC_BTFSS, jop);
4767           
4768       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4769       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4770     }
4771
4772
4773     /* mark the icode as generated */
4774     ic->generated = 1;
4775 }
4776
4777 #if 0
4778 // not needed ATM
4779
4780 /*-----------------------------------------------------------------*/
4781 /* genSkip                                                         */
4782 /*-----------------------------------------------------------------*/
4783 static void genSkip(iCode *ifx,int status_bit)
4784 {
4785   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4786   if(!ifx)
4787     return;
4788
4789   if ( IC_TRUE(ifx) ) {
4790     switch(status_bit) {
4791     case 'z':
4792       emitSKPNZ;
4793       break;
4794
4795     case 'c':
4796       emitSKPNC;
4797       break;
4798
4799     case 'd':
4800       emitSKPDC;
4801       break;
4802
4803     }
4804
4805     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4806     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4807
4808   } else {
4809
4810     switch(status_bit) {
4811
4812     case 'z':
4813       emitSKPZ;
4814       break;
4815
4816     case 'c':
4817       emitSKPC;
4818       break;
4819
4820     case 'd':
4821       emitSKPDC;
4822       break;
4823     }
4824     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4825     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4826
4827   }
4828
4829 }
4830 #endif
4831
4832 /*-----------------------------------------------------------------*/
4833 /* genSkipc                                                        */
4834 /*-----------------------------------------------------------------*/
4835 static void genSkipc(resolvedIfx *rifx)
4836 {
4837   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4838   
4839   if(!rifx)
4840     return;
4841
4842   if(rifx->condition)
4843     emitSKPNC;
4844   else
4845     emitSKPC;
4846
4847   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4848   rifx->generated = 1;
4849 }
4850
4851 #if !(USE_SIMPLE_GENCMP)
4852 /*-----------------------------------------------------------------*/
4853 /* genSkipz2                                                       */
4854 /*-----------------------------------------------------------------*/
4855 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4856 {
4857   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4858   
4859   if(!rifx)
4860     return;
4861
4862   if( (rifx->condition ^ invert_condition) & 1)
4863     emitSKPZ;
4864   else
4865     emitSKPNZ;
4866
4867   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4868   rifx->generated = 1;
4869 }
4870 #endif
4871
4872 #if 0
4873 /*-----------------------------------------------------------------*/
4874 /* genSkipz                                                        */
4875 /*-----------------------------------------------------------------*/
4876 static void genSkipz(iCode *ifx, int condition)
4877 {
4878   if(!ifx)
4879     return;
4880
4881   if(condition)
4882     emitSKPNZ;
4883   else
4884     emitSKPZ;
4885
4886   if ( IC_TRUE(ifx) )
4887     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4888   else
4889     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4890
4891   if ( IC_TRUE(ifx) )
4892     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4893   else
4894     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4895
4896 }
4897 #endif
4898
4899 #if !(USE_SIMPLE_GENCMP)
4900 /*-----------------------------------------------------------------*/
4901 /* genSkipCond                                                     */
4902 /*-----------------------------------------------------------------*/
4903 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4904 {
4905   if(!rifx)
4906     return;
4907
4908   if(rifx->condition)
4909     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4910   else
4911     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4912
4913
4914   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4915   rifx->generated = 1;
4916 }
4917 #endif
4918
4919 #if 0
4920 /*-----------------------------------------------------------------*/
4921 /* genChkZeroes :- greater or less than comparison                 */
4922 /*     For each byte in a literal that is zero, inclusive or the   */
4923 /*     the corresponding byte in the operand with W                */
4924 /*     returns true if any of the bytes are zero                   */
4925 /*-----------------------------------------------------------------*/
4926 static int genChkZeroes(operand *op, int lit,  int size)
4927 {
4928
4929   int i;
4930   int flag =1;
4931
4932   while(size--) {
4933     i = (lit >> (size*8)) & 0xff;
4934
4935     if(i==0) {
4936       if(flag) 
4937         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4938       else
4939         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4940       flag = 0;
4941     }
4942   }
4943
4944   return (flag==0);
4945 }
4946 #endif
4947
4948
4949 /*-----------------------------------------------------------------*/
4950 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4951 /*                  aop (if it's NOT a literal) or from lit (if    */
4952 /*                  aop is a literal)                              */
4953 /*-----------------------------------------------------------------*/
4954 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4955   if (aop->type == AOP_LIT) {
4956     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4957   } else {
4958     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4959   }
4960 }
4961
4962 /*-----------------------------------------------------------------*/
4963 /* genCmp :- greater or less than comparison                       */
4964 /*-----------------------------------------------------------------*/
4965
4966 #if USE_SIMPLE_GENCMP           /* { */
4967
4968 /* genCmp performs a left < right comparison, stores
4969  * the outcome in result (if != NULL) and generates
4970  * control flow code for the ifx (if != NULL).
4971  *
4972  * This version leaves in sequences like
4973  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4974  * which should be optmized by the peephole
4975  * optimizer - RN 2005-01-01 */
4976 static void genCmp (operand *left,operand *right,
4977                     operand *result, iCode *ifx, int sign)
4978 {
4979   resolvedIfx rIfx;
4980   int size;
4981   int offs;
4982   symbol *templbl;
4983   operand *dummy;
4984   unsigned long lit;
4985   unsigned long mask;
4986   int performedLt;
4987
4988   FENTRY;
4989   
4990   assert (AOP_SIZE(left) == AOP_SIZE(right));
4991   assert (left && right);
4992
4993   size = AOP_SIZE(right) - 1;
4994   mask = (0x100UL << (size*8)) - 1;
4995   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4996   performedLt = 1;
4997   templbl = NULL;
4998   lit = 0;
4999   
5000   resolveIfx (&rIfx, ifx);
5001
5002   /* handle for special cases */
5003   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5004       return;
5005
5006   /**********************************************************************
5007    * handle bits - bit compares are promoted to int compares seemingly! *
5008    **********************************************************************/
5009 #if 0
5010   // THIS IS COMPLETELY UNTESTED!
5011   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5012     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5013     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5014     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5015
5016     emitSETC;
5017     // 1 < {0,1} is false --> clear C by skipping the next instruction
5018     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5019     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5020     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5021     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5022     emitCLRC; // only skipped for left=0 && right=1
5023
5024     goto correct_result_in_carry;
5025   } // if
5026 #endif
5027
5028   /*************************************************
5029    * make sure that left is register (or the like) *
5030    *************************************************/
5031   if (!isAOP_REGlike(left)) {
5032     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5033     assert (isAOP_LIT(left));
5034     assert (isAOP_REGlike(right));
5035     // swap left and right
5036     // left < right <==> right > left <==> (right >= left + 1)
5037     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5038
5039     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5040       // MAXVALUE < right? always false
5041       if (performedLt) emitCLRC; else emitSETC;
5042       goto correct_result_in_carry;
5043     } // if
5044
5045     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5046     // that's why we handled it above.
5047     lit++;
5048
5049     dummy = left;
5050     left = right;
5051     right = dummy;
5052
5053     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
5054   } else if (isAOP_LIT(right)) {
5055     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5056   } // if
5057
5058   assert (isAOP_REGlike(left)); // left must be register or the like
5059   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5060
5061   /*************************************************
5062    * special cases go here                         *
5063    *************************************************/
5064
5065   if (isAOP_LIT(right)) {
5066     if (!sign) {
5067       // unsigned comparison to a literal
5068       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5069       if (lit == 0) {
5070         // unsigned left < 0? always false
5071         if (performedLt) emitCLRC; else emitSETC;
5072         goto correct_result_in_carry;
5073       }
5074     } else {
5075       // signed comparison to a literal
5076       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5077       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5078         // signed left < 0x80000000? always false
5079         if (performedLt) emitCLRC; else emitSETC;
5080         goto correct_result_in_carry;
5081       } else if (lit == 0) {
5082         // compare left < 0; set CARRY if SIGNBIT(left) is set
5083         if (performedLt) emitSETC; else emitCLRC;
5084         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5085         if (performedLt) emitCLRC; else emitSETC;
5086         goto correct_result_in_carry;
5087       }
5088     } // if (!sign)
5089   } // right is literal
5090
5091   /*************************************************
5092    * perform a general case comparison             *
5093    * make sure we get CARRY==1 <==> left >= right  *
5094    *************************************************/
5095   // compare most significant bytes
5096   //DEBUGpc ("comparing bytes at offset %d", size);
5097   if (!sign) {
5098     // unsigned comparison
5099     mov2w_regOrLit (AOP(right), lit, size);
5100     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5101   } else {
5102     // signed comparison
5103     // (add 2^n to both operands then perform an unsigned comparison)
5104     if (isAOP_LIT(right)) {
5105       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5106       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5107
5108       if (litbyte == 0x80) {
5109         // left >= 0x80 -- always true, but more bytes to come
5110         pic16_mov2w (AOP(left), size);
5111         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5112         emitSETC;
5113       } else {
5114         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5115         pic16_mov2w (AOP(left), size);
5116         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5117         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5118       } // if
5119     } else {
5120       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5121       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5122       pic16_mov2w (AOP(left), size);
5123       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5124       pic16_emitpcode (POC_MOVWF, pctemp);
5125       pic16_mov2w (AOP(right), size);
5126       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5127       pic16_emitpcode (POC_SUBFW, pctemp);
5128       //pic16_popReleaseTempReg(pctemp, 1);
5129     }
5130   } // if (!sign)
5131
5132   // compare remaining bytes (treat as unsigned case from above)
5133   templbl = newiTempLabel ( NULL );
5134   offs = size;
5135   while (offs--) {
5136     //DEBUGpc ("comparing bytes at offset %d", offs);
5137     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5138     mov2w_regOrLit (AOP(right), lit, offs);
5139     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5140   } // while (offs)
5141   pic16_emitpLabel (templbl->key);
5142   goto result_in_carry;
5143
5144 result_in_carry:
5145   
5146   /****************************************************
5147    * now CARRY contains the result of the comparison: *
5148    * SUBWF sets CARRY iff                             *
5149    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5150    * (F=left, W=right)                                *
5151    ****************************************************/
5152
5153   if (performedLt) {
5154     if (result && AOP_TYPE(result) != AOP_CRY) {
5155       // value will be stored
5156       emitTOGC;
5157     } else {
5158       // value wil only be used in the following genSkipc()
5159       rIfx.condition ^= 1;
5160     }
5161   } // if
5162
5163 correct_result_in_carry:
5164
5165   // assign result to variable (if neccessary)
5166   if (result && AOP_TYPE(result) != AOP_CRY) {
5167     //DEBUGpc ("assign result");
5168     size = AOP_SIZE(result);
5169     while (size--) {
5170       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5171     } // while
5172     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5173   } // if (result)
5174
5175   // perform conditional jump
5176   if (ifx) {
5177     //DEBUGpc ("generate control flow");
5178     genSkipc (&rIfx);
5179     ifx->generated = 1;
5180   } // if
5181 }
5182
5183 #elif 1         /* } */
5184                 /* { */
5185       /* original code */
5186 static void genCmp (operand *left,operand *right,
5187                     operand *result, iCode *ifx, int sign)
5188 {
5189   int size; //, offset = 0 ;
5190   unsigned long lit = 0L,i = 0;
5191   resolvedIfx rFalseIfx;
5192   //  resolvedIfx rTrueIfx;
5193   symbol *truelbl;
5194   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5195 /*
5196   if(ifx) {
5197     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5198     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5199   }
5200 */
5201
5202   FENTRY;
5203   
5204   resolveIfx(&rFalseIfx,ifx);
5205   truelbl  = newiTempLabel(NULL);
5206   size = max(AOP_SIZE(left),AOP_SIZE(right));
5207
5208   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5209
5210 #define _swapp
5211
5212   /* if literal is on the right then swap with left */
5213   if ((AOP_TYPE(right) == AOP_LIT)) {
5214     operand *tmp = right ;
5215     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5216     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5217 #ifdef _swapp
5218
5219     lit = (lit - 1) & mask;
5220     right = left;
5221     left = tmp;
5222     rFalseIfx.condition ^= 1;
5223 #endif
5224
5225   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5226     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5227   }
5228
5229
5230   //if(IC_TRUE(ifx) == NULL)
5231   /* if left & right are bit variables */
5232   if (AOP_TYPE(left) == AOP_CRY &&
5233       AOP_TYPE(right) == AOP_CRY ) {
5234     assert (0 && "bit variables used in genCmp");
5235     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5236     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5237   } else {
5238     /* subtract right from left if at the
5239        end the carry flag is set then we know that
5240        left is greater than right */
5241
5242     symbol *lbl  = newiTempLabel(NULL);
5243
5244 #if 0
5245         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5246                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5247 #endif
5248
5249 #ifndef _swapp
5250     if(AOP_TYPE(right) == AOP_LIT) {
5251
5252       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5253
5254       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5255
5256       /* special cases */
5257
5258       if(lit == 0) {
5259
5260         if(sign != 0) 
5261           genSkipCond(&rFalseIfx,left,size-1,7);
5262         else 
5263           /* no need to compare to 0...*/
5264           /* NOTE: this is a de-generate compare that most certainly 
5265            *       creates some dead code. */
5266           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5267
5268         if(ifx) ifx->generated = 1;
5269         return;
5270
5271       }
5272       size--;
5273
5274       if(size == 0) {
5275         //i = (lit >> (size*8)) & 0xff;
5276         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5277         
5278         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5279
5280         i = ((0-lit) & 0xff);
5281         if(sign) {
5282           if( i == 0x81) { 
5283             /* lit is 0x7f, all signed chars are less than
5284              * this except for 0x7f itself */
5285             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5286             genSkipz2(&rFalseIfx,0);
5287           } else {
5288             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5289             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5290             genSkipc(&rFalseIfx);
5291           }
5292
5293         } else {
5294           if(lit == 1) {
5295             genSkipz2(&rFalseIfx,1);
5296           } else {
5297             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5298             genSkipc(&rFalseIfx);
5299           }
5300         }
5301
5302         if(ifx) ifx->generated = 1;
5303         return;
5304       }
5305
5306       /* chars are out of the way. now do ints and longs */
5307
5308
5309       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5310         
5311       /* special cases */
5312
5313       if(sign) {
5314
5315         if(lit == 0) {
5316           genSkipCond(&rFalseIfx,left,size,7);
5317           if(ifx) ifx->generated = 1;
5318           return;
5319         }
5320
5321         if(lit <0x100) {
5322           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5323
5324           //rFalseIfx.condition ^= 1;
5325           //genSkipCond(&rFalseIfx,left,size,7);
5326           //rFalseIfx.condition ^= 1;
5327
5328           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5329           if(rFalseIfx.condition)
5330             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5331           else
5332             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5333
5334           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5335           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5336           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5337
5338           while(size > 1)
5339             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5340
5341           if(rFalseIfx.condition) {
5342             emitSKPZ;
5343             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5344
5345           } else {
5346             emitSKPNZ;
5347           }
5348
5349           genSkipc(&rFalseIfx);
5350           pic16_emitpLabel(truelbl->key);
5351           if(ifx) ifx->generated = 1;
5352           return;
5353
5354         }
5355
5356         if(size == 1) {
5357
5358           if( (lit & 0xff) == 0) {
5359             /* lower byte is zero */
5360             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5361             i = ((lit >> 8) & 0xff) ^0x80;
5362             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5363             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5364             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5365             genSkipc(&rFalseIfx);
5366
5367
5368             if(ifx) ifx->generated = 1;
5369             return;
5370
5371           }
5372         } else {
5373           /* Special cases for signed longs */
5374           if( (lit & 0xffffff) == 0) {
5375             /* lower byte is zero */
5376             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5377             i = ((lit >> 8*3) & 0xff) ^0x80;
5378             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5379             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5380             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5381             genSkipc(&rFalseIfx);
5382
5383
5384             if(ifx) ifx->generated = 1;
5385             return;
5386
5387           }
5388
5389         }
5390
5391
5392         if(lit & (0x80 << (size*8))) {
5393           /* lit is negative */
5394           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5395
5396           //genSkipCond(&rFalseIfx,left,size,7);
5397
5398           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5399
5400           if(rFalseIfx.condition)
5401             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5402           else
5403             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5404
5405
5406         } else {
5407           /* lit is positive */
5408           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5409           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5410           if(rFalseIfx.condition)
5411             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5412           else
5413             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5414
5415         }
5416
5417         /*
5418           This works, but is only good for ints.
5419           It also requires a "known zero" register.
5420           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5421           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5422           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5423           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5424           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5425           genSkipc(&rFalseIfx);
5426
5427           pic16_emitpLabel(truelbl->key);
5428           if(ifx) ifx->generated = 1;
5429           return;
5430         **/
5431           
5432         /* There are no more special cases, so perform a general compare */
5433   
5434         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5435         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5436
5437         while(size--) {
5438
5439           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5440           emitSKPNZ;
5441           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5442         }
5443         //rFalseIfx.condition ^= 1;
5444         genSkipc(&rFalseIfx);
5445
5446         pic16_emitpLabel(truelbl->key);
5447
5448         if(ifx) ifx->generated = 1;
5449         return;
5450
5451
5452       }
5453
5454
5455       /* sign is out of the way. So now do an unsigned compare */
5456       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5457
5458
5459       /* General case - compare to an unsigned literal on the right.*/
5460
5461       i = (lit >> (size*8)) & 0xff;
5462       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5463       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5464       while(size--) {
5465         i = (lit >> (size*8)) & 0xff;
5466
5467         if(i) {
5468           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5469           emitSKPNZ;
5470           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5471         } else {
5472           /* this byte of the lit is zero, 
5473            *if it's not the last then OR in the variable */
5474           if(size)
5475             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5476         }
5477       }
5478
5479
5480       pic16_emitpLabel(lbl->key);
5481 //      pic16_emitpLabel(truelbl->key);
5482       //if(emitFinalCheck)
5483       genSkipc(&rFalseIfx);
5484       if(sign)
5485         pic16_emitpLabel(truelbl->key);
5486
5487       if(ifx) ifx->generated = 1;
5488       return;
5489
5490
5491     }
5492 #endif  // _swapp
5493
5494     if(AOP_TYPE(left) == AOP_LIT) {
5495       //symbol *lbl = newiTempLabel(NULL);
5496
5497       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5498
5499
5500       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5501
5502       /* Special cases */
5503       if((lit == 0) && (sign == 0)){
5504
5505         size--;
5506         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5507         while(size) 
5508           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5509
5510         genSkipz2(&rFalseIfx,0);
5511         if(ifx) ifx->generated = 1;
5512         return;
5513       }
5514
5515       if(size==1) {
5516         /* Special cases */
5517         lit &= 0xff;
5518         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5519           /* degenerate compare can never be true */
5520           if(rFalseIfx.condition == 0)
5521             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5522
5523           if(ifx) ifx->generated = 1;
5524           return;
5525         }
5526
5527         if(sign) {
5528           /* signed comparisons to a literal byte */
5529
5530           int lp1 = (lit+1) & 0xff;
5531
5532           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5533           switch (lp1) {
5534           case 0:
5535             rFalseIfx.condition ^= 1;
5536             genSkipCond(&rFalseIfx,right,0,7);
5537             break;
5538           case 0x7f:
5539             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5540             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5541             genSkipz2(&rFalseIfx,1);
5542             break;
5543           default:
5544             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5545             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5546             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5547             rFalseIfx.condition ^= 1;
5548             genSkipc(&rFalseIfx);
5549             break;
5550           }
5551         } else {
5552           /* unsigned comparisons to a literal byte */
5553
5554           switch(lit & 0xff ) {
5555           case 0:
5556             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5557             genSkipz2(&rFalseIfx,0);
5558             break;
5559           case 0x7f:
5560             rFalseIfx.condition ^= 1;
5561             genSkipCond(&rFalseIfx,right,0,7);
5562             break;
5563
5564           default:
5565             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5566             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5567             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5568             rFalseIfx.condition ^= 1;
5569             if (AOP_TYPE(result) == AOP_CRY)
5570               genSkipc(&rFalseIfx);
5571             else {
5572               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5573               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5574             }         
5575             break;
5576           }
5577         }
5578
5579         if(ifx) ifx->generated = 1;
5580         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5581                 goto check_carry;
5582         return;
5583
5584       } else {
5585
5586         /* Size is greater than 1 */
5587
5588         if(sign) {
5589           int lp1 = lit+1;
5590
5591           size--;
5592
5593           if(lp1 == 0) {
5594             /* this means lit = 0xffffffff, or -1 */
5595
5596
5597             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5598             rFalseIfx.condition ^= 1;
5599             genSkipCond(&rFalseIfx,right,size,7);
5600             if(ifx) ifx->generated = 1;
5601
5602             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5603               goto check_carry;
5604
5605             return;
5606           }
5607
5608           if(lit == 0) {
5609             int s = size;
5610
5611             if(rFalseIfx.condition) {
5612               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5613               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5614             }
5615
5616             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5617             while(size--)
5618               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5619
5620
5621             emitSKPZ;
5622             if(rFalseIfx.condition) {
5623               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5624               pic16_emitpLabel(truelbl->key);
5625             }else {
5626               rFalseIfx.condition ^= 1;
5627               genSkipCond(&rFalseIfx,right,s,7);
5628             }
5629
5630             if(ifx) ifx->generated = 1;
5631
5632             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5633               goto check_carry;
5634
5635             return;
5636           }
5637
5638           if((size == 1) &&  (0 == (lp1&0xff))) {
5639             /* lower byte of signed word is zero */
5640             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5641             i = ((lp1 >> 8) & 0xff) ^0x80;
5642             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5643             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5644             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5645
5646             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5647               emitTOGC;
5648               if(ifx) ifx->generated = 1;
5649               goto check_carry;
5650             } else {
5651               rFalseIfx.condition ^= 1;
5652               genSkipc(&rFalseIfx);
5653               if(ifx) ifx->generated = 1;
5654             }
5655
5656             return;
5657           }
5658
5659           if(lit & (0x80 << (size*8))) {
5660             /* Lit is less than zero */
5661             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5662             //rFalseIfx.condition ^= 1;
5663             //genSkipCond(&rFalseIfx,left,size,7);
5664             //rFalseIfx.condition ^= 1;
5665             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5666             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5667
5668             if(rFalseIfx.condition)
5669               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5670             else
5671               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5672
5673
5674           } else {
5675             /* Lit is greater than or equal to zero */
5676             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5677             //rFalseIfx.condition ^= 1;
5678             //genSkipCond(&rFalseIfx,right,size,7);
5679             //rFalseIfx.condition ^= 1;
5680
5681             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5682             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5683
5684             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5685             if(rFalseIfx.condition)
5686               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5687             else
5688               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5689
5690           }
5691
5692           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5693           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5694
5695           while(size--) {
5696
5697             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5698             emitSKPNZ;
5699             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5700           }
5701           rFalseIfx.condition ^= 1;
5702           //rFalseIfx.condition = 1;
5703           genSkipc(&rFalseIfx);
5704
5705           pic16_emitpLabel(truelbl->key);
5706
5707           if(ifx) ifx->generated = 1;
5708
5709
5710           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5711             goto check_carry;
5712
5713           return;
5714           // end of if (sign)
5715         } else {
5716
5717           /* compare word or long to an unsigned literal on the right.*/
5718
5719
5720           size--;
5721           if(lit < 0xff) {
5722             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5723             switch (lit) {
5724             case 0:
5725               break; /* handled above */
5726 /*
5727             case 0xff:
5728               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5729               while(size--)
5730                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5731               genSkipz2(&rFalseIfx,0);
5732               break;
5733 */
5734             default:
5735               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5736               while(--size)
5737                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5738
5739               emitSKPZ;
5740               if(rFalseIfx.condition)
5741                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5742               else
5743                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5744
5745
5746               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5747               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5748
5749               rFalseIfx.condition ^= 1;
5750               genSkipc(&rFalseIfx);
5751             }
5752
5753             pic16_emitpLabel(truelbl->key);
5754
5755             if(ifx) ifx->generated = 1;
5756
5757             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5758               goto check_carry;
5759
5760             return;
5761           }
5762
5763
5764           lit++;
5765           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5766           i = (lit >> (size*8)) & 0xff;
5767
5768           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5769           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5770
5771           while(size--) {
5772             i = (lit >> (size*8)) & 0xff;
5773
5774             if(i) {
5775               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5776               emitSKPNZ;
5777               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5778             } else {
5779               /* this byte of the lit is zero, 
5780                * if it's not the last then OR in the variable */
5781               if(size)
5782                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5783             }
5784           }
5785
5786
5787           pic16_emitpLabel(lbl->key);
5788
5789           rFalseIfx.condition ^= 1;
5790
5791           genSkipc(&rFalseIfx);
5792         }
5793
5794         if(sign)
5795           pic16_emitpLabel(truelbl->key);
5796         if(ifx) ifx->generated = 1;
5797
5798             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5799               goto check_carry;
5800
5801         return;
5802       }
5803     }
5804     /* Compare two variables */
5805
5806     DEBUGpic16_emitcode(";sign","%d",sign);
5807
5808     size--;
5809     if(sign) {
5810       /* Sigh. thus sucks... */
5811       if(size) {
5812         pCodeOp *pctemp;
5813         
5814         pctemp = pic16_popGetTempReg(1);
5815         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5816         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5817         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5818         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5819         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5820         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5821         pic16_popReleaseTempReg(pctemp, 1);
5822       } else {
5823         /* Signed char comparison */
5824         /* Special thanks to Nikolai Golovchenko for this snippet */
5825         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5826         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5827         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5828         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5829         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5830         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5831
5832         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5833         genSkipc(&rFalseIfx);
5834           
5835         if(ifx) ifx->generated = 1;
5836
5837             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5838               goto check_carry;
5839
5840         return;
5841       }
5842
5843     } else {
5844
5845       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5846       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5847     }
5848
5849
5850     /* The rest of the bytes of a multi-byte compare */
5851     while (size) {
5852
5853       emitSKPZ;
5854       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5855       size--;
5856
5857       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5858       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5859
5860
5861     }
5862
5863     pic16_emitpLabel(lbl->key);
5864
5865     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5866     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5867         (AOP_TYPE(result) == AOP_REG)) {
5868       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5869       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5870     } else {
5871       genSkipc(&rFalseIfx);
5872     }         
5873     //genSkipc(&rFalseIfx);
5874     if(ifx) ifx->generated = 1;
5875
5876
5877             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5878               goto check_carry;
5879
5880     return;
5881
5882   }
5883
5884 check_carry:
5885   if ((AOP_TYPE(result) != AOP_CRY) 
5886         && AOP_SIZE(result)) {
5887     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5888
5889     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5890
5891     pic16_outBitC(result);
5892   } else {
5893     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5894     /* if the result is used in the next
5895        ifx conditional branch then generate
5896        code a little differently */
5897     if (ifx )
5898       genIfxJump (ifx,"c");
5899     else
5900       pic16_outBitC(result);
5901     /* leave the result in acc */
5902   }
5903
5904 }
5905
5906 #elif 0 /* VR version of genCmp() */    /* } else { */
5907
5908 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5909 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5910         operand *result, int offset, int invert_op)
5911 {
5912   /* add code here */
5913   
5914   /* check condition, > or < ?? */
5915   if(rIfx->condition != 0)invert_op ^= 1;
5916   
5917   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5918
5919   if(!ifx)invert_op ^= 1;
5920
5921   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5922       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5923   
5924   /* do selection */
5925   if(!invert_op)return POC_CPFSGT;
5926   else return POC_CPFSLT;
5927 }
5928
5929 static int compareAopfirstpass=1;
5930
5931 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5932             operand *oper, int offset, operand *result,
5933             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5934             symbol *tlbl)
5935 {
5936   int op;
5937   symbol *truelbl;
5938
5939   /* invert if there is a result to be loaded, in order to fit,
5940    * SETC/CLRC sequence */
5941   if(AOP_SIZE(result))invert_op ^= 1;
5942
5943 //  if(sign && !offset)invert_op ^= 1;
5944   
5945 //  if(sign)invert_op ^= 1;
5946   
5947   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5948
5949   if(AOP_SIZE(result) && compareAopfirstpass) {
5950     if(!ifx) {
5951       if(pcop2)
5952         pic16_emitpcode(POC_SETF, pcop2);
5953       else
5954         emitSETC;
5955     } else {
5956       if(pcop2)
5957         pic16_emitpcode(POC_CLRF, pcop2);
5958       else
5959         emitCLRC;
5960     }
5961   }
5962
5963   compareAopfirstpass = 0;
5964
5965       /* there is a bug when comparing operands with size > 1,
5966        * because higher bytes can be equal and test should be performed
5967        * to the next lower byte, current algorithm, considers operands
5968        * inequal in these cases! -- VR 20041107 */
5969
5970     
5971   if(pcop)
5972     pic16_emitpcode(op, pcop);
5973   else
5974     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5975
5976
5977   if((!sign || !offset) && AOP_SIZE(result)) {
5978     if(!ifx) {
5979       if(pcop2)
5980         pic16_emitpcode(POC_CLRF, pcop2);
5981         else
5982         emitCLRC;
5983     } else {
5984       if(pcop2)
5985         pic16_emitpcode(POC_SETF, pcop2);
5986       else
5987         emitSETC;
5988     }
5989     
5990     /* don't emit final branch (offset == 0) */
5991     if(offset) {
5992
5993       if(pcop2)
5994         pic16_emitpcode(POC_RRCF, pcop2);
5995
5996       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5997     }
5998   } else {
5999     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6000       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6001             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6002
6003       truelbl = newiTempLabel( NULL );
6004       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6005       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6006         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6007       else
6008         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6009       pic16_emitpLabel(truelbl->key);
6010     } else {
6011       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6012     }
6013   }
6014 }
6015
6016 static void genCmp (operand *left, operand *right,
6017                     operand *result, iCode *ifx, int sign)
6018 {
6019   int size, cmpop=1;
6020   long lit = 0L;
6021   resolvedIfx rFalseIfx;
6022   symbol *falselbl, *tlbl;
6023
6024     FENTRY;
6025     
6026     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6027
6028     resolveIfx(&rFalseIfx, ifx);
6029     size = max(AOP_SIZE(left), AOP_SIZE(right));
6030     
6031     /* if left & right are bit variables */
6032     if(AOP_TYPE(left) == AOP_CRY
6033       && AOP_TYPE(right) == AOP_CRY ) {
6034
6035         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6036         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6037         
6038         werror(W_POSSBUG2, __FILE__, __LINE__);
6039         exit(-1);
6040     }
6041     
6042     /* if literal is on the right then swap with left */
6043     if((AOP_TYPE(right) == AOP_LIT)) {
6044       operand *tmp = right ;
6045 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
6046
6047         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6048
6049 //      lit = (lit - 1) & mask;
6050         right = left;
6051         left = tmp;
6052         rFalseIfx.condition ^= 1;               /* reverse compare */
6053     } else
6054     if ((AOP_TYPE(left) == AOP_LIT)) {
6055       /* float compares are handled by support functions */
6056       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6057     }
6058
6059     /* actual comparing algorithm */
6060 //    size = AOP_SIZE( right );
6061
6062     falselbl = newiTempLabel( NULL );
6063     if(AOP_TYPE(left) == AOP_LIT) {
6064       /* compare to literal */
6065       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6066       
6067       if(sign) {
6068         pCodeOp *pct, *pct2;
6069         symbol *tlbl1;
6070
6071         /* signed compare */
6072         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6073
6074         pct = pic16_popCopyReg(&pic16_pc_prodl);
6075         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6076         tlbl = newiTempLabel( NULL );
6077         
6078         /* first compare signs:
6079          *  a. if both are positive, compare just like unsigned
6080          *  b. if both are negative, invert cmpop, compare just like unsigned
6081          *  c. if different signs, determine the result directly */
6082
6083         size--;
6084
6085 #if 1
6086         /* { */
6087         tlbl1 = newiTempLabel( NULL );
6088 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6089
6090         if(lit > 0) {
6091
6092           /* literal is zero or positive:
6093            *  a. if carry is zero, too, continue compare,
6094            *  b. if carry is set, then continue depending on cmpop ^ condition:
6095            *    1. '<' return false (literal < variable),
6096            *    2. '>' return true (literal > variable) */
6097 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6098           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6099           
6100           
6101           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6102           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6103         } else 
6104         if(lit < 0) {
6105           
6106           /* literal is negative:
6107            *  a. if carry is set, too, continue compare,
6108            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6109            *    1. '<' return true (literal < variable),
6110            *    2. '>' return false (literal > variable) */
6111 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6112           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6113           
6114           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6115           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6116         }
6117 #if 1
6118         else {
6119           /* lit == 0 */
6120           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6121           
6122           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6123           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6124         }
6125 #endif
6126         
6127         
6128         pic16_emitpLabel( tlbl1->key );
6129 #endif  /* } */
6130
6131         compareAopfirstpass=1;
6132 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6133 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6134 //        pic16_emitpcode(POC_MOVWF, pct);
6135
6136 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6137         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6138 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6139         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6140
6141         /* generic case */        
6142           while( size-- ) {
6143 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6144 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6145 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6146 //            pic16_emitpcode(POC_MOVWF, pct);
6147
6148 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6149             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6150             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6151 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6152 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6153           }
6154 //        }
6155         
6156         if(ifx)ifx->generated = 1;
6157
6158         if(AOP_SIZE(result)) {
6159           pic16_emitpLabel(tlbl->key);
6160           pic16_emitpLabel(falselbl->key);
6161           pic16_outBitOp( result, pct2 );
6162         } else {
6163           pic16_emitpLabel(tlbl->key);
6164         }
6165       } else {
6166
6167         /* unsigned compare */      
6168         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6169     
6170         compareAopfirstpass=1;
6171         while(size--) {
6172           
6173           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6174           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6175
6176         }
6177         if(ifx)ifx->generated = 1;
6178
6179         if(AOP_SIZE(result)) {
6180           pic16_emitpLabel(falselbl->key);
6181           pic16_outBitC( result );
6182         }
6183
6184       }
6185     } else {
6186       /* compare registers */
6187       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6188
6189
6190       if(sign) {
6191         pCodeOp *pct, *pct2;
6192         
6193         /* signed compare */
6194         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6195
6196         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6197         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6198         tlbl = newiTempLabel( NULL );
6199         
6200         compareAopfirstpass=1;
6201
6202         size--;
6203         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6204 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6205         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6206         pic16_emitpcode(POC_MOVWF, pct);
6207
6208         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6209 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6210         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6211
6212         /* WREG already holds left + 0x80 */
6213         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6214         
6215         while( size-- ) {
6216           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6217 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6218           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6219           pic16_emitpcode(POC_MOVWF, pct);
6220                 
6221           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6222 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6223           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6224
6225           /* WREG already holds left + 0x80 */
6226           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6227 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6228         }
6229         
6230         if(ifx)ifx->generated = 1;
6231
6232         if(AOP_SIZE(result)) {
6233           pic16_emitpLabel(tlbl->key);
6234           pic16_emitpLabel(falselbl->key);
6235           pic16_outBitOp( result, pct2 );
6236         } else {
6237           pic16_emitpLabel(tlbl->key);
6238         }
6239
6240       } else {
6241         /* unsigned compare */      
6242         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6243
6244         compareAopfirstpass=1;
6245         while(size--) {
6246           
6247           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6248           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6249
6250         }
6251
6252         if(ifx)ifx->generated = 1;
6253         if(AOP_SIZE(result)) {
6254
6255           pic16_emitpLabel(falselbl->key);
6256           pic16_outBitC( result );
6257         }
6258
6259       }
6260     }
6261 }
6262
6263 #endif  /* } */
6264
6265
6266
6267 /*-----------------------------------------------------------------*/
6268 /* genCmpGt :- greater than comparison                             */
6269 /*-----------------------------------------------------------------*/
6270 static void genCmpGt (iCode *ic, iCode *ifx)
6271 {
6272   operand *left, *right, *result;
6273   sym_link *letype , *retype;
6274   int sign ;
6275
6276     FENTRY;
6277     
6278     left = IC_LEFT(ic);
6279     right= IC_RIGHT(ic);
6280     result = IC_RESULT(ic);
6281
6282     letype = getSpec(operandType(left));
6283     retype =getSpec(operandType(right));
6284     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6285     /* assign the amsops */
6286     pic16_aopOp (left,ic,FALSE);
6287     pic16_aopOp (right,ic,FALSE);
6288     pic16_aopOp (result,ic,TRUE);
6289
6290     genCmp(right, left, result, ifx, sign);
6291
6292     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6293     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6294     pic16_freeAsmop(result,NULL,ic,TRUE); 
6295 }
6296
6297 /*-----------------------------------------------------------------*/
6298 /* genCmpLt - less than comparisons                                */
6299 /*-----------------------------------------------------------------*/
6300 static void genCmpLt (iCode *ic, iCode *ifx)
6301 {
6302   operand *left, *right, *result;
6303   sym_link *letype , *retype;
6304   int sign ;
6305
6306     FENTRY;
6307
6308     left = IC_LEFT(ic);
6309     right= IC_RIGHT(ic);
6310     result = IC_RESULT(ic);
6311
6312     letype = getSpec(operandType(left));
6313     retype =getSpec(operandType(right));
6314     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6315
6316     /* assign the amsops */
6317     pic16_aopOp (left,ic,FALSE);
6318     pic16_aopOp (right,ic,FALSE);
6319     pic16_aopOp (result,ic,TRUE);
6320
6321     genCmp(left, right, result, ifx, sign);
6322
6323     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6324     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6325     pic16_freeAsmop(result,NULL,ic,TRUE); 
6326 }
6327
6328 #if 0
6329 // not needed ATM
6330 // FIXME reenable literal optimisation when the pic16 port is stable
6331
6332 /*-----------------------------------------------------------------*/
6333 /* genc16bit2lit - compare a 16 bit value to a literal             */
6334 /*-----------------------------------------------------------------*/
6335 static void genc16bit2lit(operand *op, int lit, int offset)
6336 {
6337   int i;
6338
6339   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6340   if( (lit&0xff) == 0) 
6341     i=1;
6342   else
6343     i=0;
6344
6345   switch( BYTEofLONG(lit,i)) { 
6346   case 0:
6347     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6348     break;
6349   case 1:
6350     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6351     break;
6352   case 0xff:
6353     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6354     break;
6355   default:
6356     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6357     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6358   }
6359
6360   i ^= 1;
6361
6362   switch( BYTEofLONG(lit,i)) { 
6363   case 0:
6364     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6365     break;
6366   case 1:
6367     emitSKPNZ;
6368     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6369     break;
6370   case 0xff:
6371     emitSKPNZ;
6372     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6373     break;
6374   default:
6375     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6376     emitSKPNZ;
6377     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6378
6379   }
6380
6381 }
6382 #endif
6383
6384 #if 0
6385 // not needed ATM
6386 /*-----------------------------------------------------------------*/
6387 /* gencjneshort - compare and jump if not equal                    */
6388 /*-----------------------------------------------------------------*/
6389 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6390 {
6391   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6392   int offset = 0;
6393   int res_offset = 0;  /* the result may be a different size then left or right */
6394   int res_size = AOP_SIZE(result);
6395   resolvedIfx rIfx;
6396   symbol *lbl, *lbl_done;
6397
6398   unsigned long lit = 0L;
6399   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6400
6401   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6402   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6403   if(result)
6404     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6405   resolveIfx(&rIfx,ifx);
6406   lbl =  newiTempLabel(NULL);
6407   lbl_done =  newiTempLabel(NULL);
6408
6409
6410   /* if the left side is a literal or 
6411      if the right is in a pointer register and left 
6412      is not */
6413   if ((AOP_TYPE(left) == AOP_LIT) || 
6414       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6415     operand *t = right;
6416     right = left;
6417     left = t;
6418   }
6419   if(AOP_TYPE(right) == AOP_LIT)
6420     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6421
6422   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6423     preserve_result = 1;
6424
6425   if(result && !preserve_result)
6426     {
6427       int i;
6428       for(i = 0; i < AOP_SIZE(result); i++)
6429         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6430     }
6431
6432
6433   /* if the right side is a literal then anything goes */
6434   if (AOP_TYPE(right) == AOP_LIT &&
6435       AOP_TYPE(left) != AOP_DIR ) {
6436     switch(size) {
6437     case 2:
6438       genc16bit2lit(left, lit, 0);
6439       emitSKPZ;
6440       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6441       break;
6442     default:
6443       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6444       while (size--) {
6445         if(lit & 0xff) {
6446           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6447           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6448         } else {
6449           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6450         }
6451
6452         emitSKPZ;
6453         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6454         offset++;
6455         if(res_offset < res_size-1)
6456           res_offset++;
6457         lit >>= 8;
6458       }
6459       break;
6460     }
6461   }
6462
6463   /* if the right side is in a register or in direct space or
6464      if the left is a pointer register & right is not */    
6465   else if (AOP_TYPE(right) == AOP_REG ||
6466            AOP_TYPE(right) == AOP_DIR || 
6467            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6468            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6469     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6470     int lbl_key = lbl->key;
6471
6472     if(result) {
6473       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6474       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6475     }else {
6476       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6477       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6478               __FUNCTION__,__LINE__);
6479       return;
6480     }
6481    
6482 /*     switch(size) { */
6483 /*     case 2: */
6484 /*       genc16bit2lit(left, lit, 0); */
6485 /*       emitSKPNZ; */
6486 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6487 /*       break; */
6488 /*     default: */
6489     while (size--) {
6490       int emit_skip=1;
6491       if((AOP_TYPE(left) == AOP_DIR) && 
6492          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6493
6494         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6495         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6496
6497       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6498             
6499         switch (lit & 0xff) {
6500         case 0:
6501           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6502           break;
6503         case 1:
6504           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6505           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6506           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6507           emit_skip=0;
6508           break;
6509         case 0xff:
6510           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6511           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6512           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6513           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6514           emit_skip=0;
6515           break;
6516         default:
6517           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6518           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6519         }
6520         lit >>= 8;
6521
6522       } else {
6523         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6524       }
6525       if(emit_skip) {
6526         if(AOP_TYPE(result) == AOP_CRY) {
6527           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6528           if(rIfx.condition)
6529             emitSKPNZ;
6530           else
6531             emitSKPZ;
6532           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6533         } else {
6534           /* fix me. probably need to check result size too */
6535           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6536           if(rIfx.condition)
6537             emitSKPZ;
6538           else
6539             emitSKPNZ;
6540           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6541           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6542         }
6543         if(ifx)
6544           ifx->generated=1;
6545       }
6546       emit_skip++;
6547       offset++;
6548       if(res_offset < res_size-1)
6549         res_offset++;
6550     }
6551 /*       break; */
6552 /*     } */
6553   } else if(AOP_TYPE(right) == AOP_REG &&
6554             AOP_TYPE(left) != AOP_DIR){
6555
6556     while(size--) {
6557       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6558       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6559       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6560       if(rIfx.condition)
6561         emitSKPNZ;
6562       else
6563         emitSKPZ;
6564       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6565       offset++;
6566       if(res_offset < res_size-1)
6567         res_offset++;
6568     }
6569       
6570   }else{
6571     /* right is a pointer reg need both a & b */
6572     while(size--) {
6573       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6574       if(strcmp(l,"b"))
6575         pic16_emitcode("mov","b,%s",l);
6576       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6577       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6578       offset++;
6579     }
6580   }
6581
6582   if(result && preserve_result)
6583     {
6584       int i;
6585       for(i = 0; i < AOP_SIZE(result); i++)
6586         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6587     }
6588
6589   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6590
6591   if(result && preserve_result)
6592     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6593
6594   if(!rIfx.condition)
6595     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6596
6597   pic16_emitpLabel(lbl->key);
6598
6599   if(result && preserve_result)
6600     {
6601       int i;
6602       for(i = 0; i < AOP_SIZE(result); i++)
6603         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6604
6605       pic16_emitpLabel(lbl_done->key);
6606    }
6607
6608   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6609
6610   if(ifx)
6611     ifx->generated = 1;
6612 }
6613 #endif
6614
6615 #if 0
6616 /*-----------------------------------------------------------------*/
6617 /* gencjne - compare and jump if not equal                         */
6618 /*-----------------------------------------------------------------*/
6619 static void gencjne(operand *left, operand *right, iCode *ifx)
6620 {
6621     symbol *tlbl  = newiTempLabel(NULL);
6622
6623     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6624     gencjneshort(left, right, lbl);
6625
6626     pic16_emitcode("mov","a,%s",one);
6627     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6628     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6629     pic16_emitcode("clr","a");
6630     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6631
6632     pic16_emitpLabel(lbl->key);
6633     pic16_emitpLabel(tlbl->key);
6634
6635 }
6636 #endif
6637
6638
6639 /*-----------------------------------------------------------------*/
6640 /* is_LitOp - check if operand has to be treated as literal        */
6641 /*-----------------------------------------------------------------*/
6642 static bool is_LitOp(operand *op)
6643 {
6644   return ((AOP_TYPE(op) == AOP_LIT)
6645       || ( (AOP_TYPE(op) == AOP_PCODE)
6646           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6647               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6648 }
6649
6650 /*-----------------------------------------------------------------*/
6651 /* is_LitAOp - check if operand has to be treated as literal        */
6652 /*-----------------------------------------------------------------*/
6653 static bool is_LitAOp(asmop *aop)
6654 {
6655   return ((aop->type == AOP_LIT)
6656       || ( (aop->type == AOP_PCODE)
6657           && ( (aop->aopu.pcop->type == PO_LITERAL)
6658               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6659 }
6660
6661
6662
6663 /*-----------------------------------------------------------------*/
6664 /* genCmpEq - generates code for equal to                          */
6665 /*-----------------------------------------------------------------*/
6666 static void genCmpEq (iCode *ic, iCode *ifx)
6667 {
6668   operand *left, *right, *result;
6669   symbol *falselbl = newiTempLabel(NULL);
6670   symbol *donelbl = newiTempLabel(NULL);
6671
6672   int preserve_result = 0;
6673   int generate_result = 0;
6674   int i=0;
6675   unsigned long lit = -1;
6676
6677   FENTRY;
6678   
6679   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6680   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6681   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6682  
6683   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6684
6685   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6686     {
6687       werror(W_POSSBUG2, __FILE__, __LINE__);
6688       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6689       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6690       goto release;
6691     }
6692
6693   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6694     {
6695       operand *tmp = right ;
6696       right = left;
6697       left = tmp;
6698     }
6699
6700   if (AOP_TYPE(right) == AOP_LIT) {
6701     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6702   }
6703
6704   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6705     preserve_result = 1;
6706
6707   if(result && AOP_SIZE(result))
6708     generate_result = 1;
6709
6710   if(generate_result && !preserve_result)
6711     {
6712       for(i = 0; i < AOP_SIZE(result); i++)
6713         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6714     }
6715
6716   for(i=0; i < AOP_SIZE(left); i++)
6717     {
6718       if(AOP_TYPE(left) != AOP_ACC)
6719         {
6720           if(is_LitOp(left))
6721             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6722           else
6723             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6724         }
6725       if(is_LitOp(right)) {
6726         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6727           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6728         }
6729       } else
6730         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6731
6732       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6733     }
6734
6735   // result == true
6736
6737   if(generate_result && preserve_result)
6738     {
6739       for(i = 0; i < AOP_SIZE(result); i++)
6740         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6741     }
6742
6743   if(generate_result)
6744     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6745
6746   if(generate_result && preserve_result)
6747     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6748
6749   if(ifx && IC_TRUE(ifx))
6750     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6751
6752   if(ifx && IC_FALSE(ifx))
6753     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6754
6755   pic16_emitpLabel(falselbl->key);
6756
6757   // result == false
6758
6759   if(ifx && IC_FALSE(ifx))
6760     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6761
6762   if(generate_result && preserve_result)
6763     {
6764       for(i = 0; i < AOP_SIZE(result); i++)
6765         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6766     }
6767
6768   pic16_emitpLabel(donelbl->key);
6769
6770   if(ifx)
6771     ifx->generated = 1;
6772
6773 release:
6774   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6775   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6776   pic16_freeAsmop(result,NULL,ic,TRUE);
6777
6778 }
6779
6780
6781 #if 0
6782 // old version kept for reference
6783
6784 /*-----------------------------------------------------------------*/
6785 /* genCmpEq - generates code for equal to                          */
6786 /*-----------------------------------------------------------------*/
6787 static void genCmpEq (iCode *ic, iCode *ifx)
6788 {
6789     operand *left, *right, *result;
6790     unsigned long lit = 0L;
6791     int size,offset=0;
6792     symbol *falselbl  = newiTempLabel(NULL);
6793
6794
6795     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6796
6797     if(ifx)
6798       DEBUGpic16_emitcode ("; ifx is non-null","");
6799     else
6800       DEBUGpic16_emitcode ("; ifx is null","");
6801
6802     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6803     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6804     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6805
6806     size = max(AOP_SIZE(left),AOP_SIZE(right));
6807
6808     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6809
6810     /* if literal, literal on the right or 
6811     if the right is in a pointer register and left 
6812     is not */
6813     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6814         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6815       operand *tmp = right ;
6816       right = left;
6817       left = tmp;
6818     }
6819
6820
6821     if(ifx && !AOP_SIZE(result)){
6822         symbol *tlbl;
6823         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6824         /* if they are both bit variables */
6825         if (AOP_TYPE(left) == AOP_CRY &&
6826             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6827                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6828             if(AOP_TYPE(right) == AOP_LIT){
6829                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6830                 if(lit == 0L){
6831                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6832                     pic16_emitcode("cpl","c");
6833                 } else if(lit == 1L) {
6834                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6835                 } else {
6836                     pic16_emitcode("clr","c");
6837                 }
6838                 /* AOP_TYPE(right) == AOP_CRY */
6839             } else {
6840                 symbol *lbl = newiTempLabel(NULL);
6841                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6842                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6843                 pic16_emitcode("cpl","c");
6844                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6845             }
6846             /* if true label then we jump if condition
6847             supplied is true */
6848             tlbl = newiTempLabel(NULL);
6849             if ( IC_TRUE(ifx) ) {
6850                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6851                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6852             } else {
6853                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6854                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6855             }
6856             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6857
6858                 {
6859                 /* left and right are both bit variables, result is carry */
6860                         resolvedIfx rIfx;
6861               
6862                         resolveIfx(&rIfx,ifx);
6863
6864                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6865                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6866                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6867                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6868                         genSkipz2(&rIfx,0);
6869                 }
6870         } else {
6871
6872                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6873
6874                         /* They're not both bit variables. Is the right a literal? */
6875                         if(AOP_TYPE(right) == AOP_LIT) {
6876                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6877             
6878                         switch(size) {
6879
6880                                 case 1:
6881                                         switch(lit & 0xff) {
6882                                                 case 1:
6883                                                                 if ( IC_TRUE(ifx) ) {
6884                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6885                                                                         emitSKPNZ;
6886                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6887                                                                 } else {
6888                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6889                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6890                                                                 }
6891                                                                 break;
6892                                                 case 0xff:
6893                                                                 if ( IC_TRUE(ifx) ) {
6894                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6895                                                                         emitSKPNZ;
6896                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6897                                                                 } else {
6898                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6899                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6900                                                                 }
6901                                                                 break;
6902                                                 default:
6903                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6904                                                                 if(lit)
6905                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6906                                                                 genSkip(ifx,'z');
6907                                         } // switch lit
6908
6909
6910                                         /* end of size == 1 */
6911                                         break;
6912               
6913                                 case 2:
6914                                         genc16bit2lit(left,lit,offset);
6915                                         genSkip(ifx,'z');
6916                                         break;
6917                                         /* end of size == 2 */
6918
6919                                 default:
6920                                         /* size is 4 */
6921                                         if(lit==0) {
6922                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6923                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6924                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6925                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6926                                                 genSkip(ifx,'z');
6927                                         } else {
6928                                                 /* search for patterns that can be optimized */
6929
6930                                                 genc16bit2lit(left,lit,0);
6931                                                 lit >>= 16;
6932                                                 if(lit) {
6933                                                                 if(IC_TRUE(ifx))
6934                                                                 emitSKPZ; // if hi word unequal
6935                                                                 else
6936                                                                 emitSKPNZ; // if hi word equal
6937                                                                 // fail early
6938                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6939                                                         genc16bit2lit(left,lit,2);
6940                                                         genSkip(ifx,'z');
6941                                                 } else {
6942                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6943                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6944                                                         genSkip(ifx,'z');
6945                                                 }
6946                                         }
6947                                                 pic16_emitpLabel(falselbl->key);
6948                                                 break;
6949
6950                         } // switch size
6951           
6952                         ifx->generated = 1;
6953                         goto release ;
6954             
6955
6956           } else if(AOP_TYPE(right) == AOP_CRY ) {
6957             /* we know the left is not a bit, but that the right is */
6958             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6959             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6960                       pic16_popGet(AOP(right),offset));
6961             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6962
6963             /* if the two are equal, then W will be 0 and the Z bit is set
6964              * we could test Z now, or go ahead and check the high order bytes if
6965              * the variable we're comparing is larger than a byte. */
6966
6967             while(--size)
6968               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6969
6970             if ( IC_TRUE(ifx) ) {
6971               emitSKPNZ;
6972               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6973               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6974             } else {
6975               emitSKPZ;
6976               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6977               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6978             }
6979
6980           } else {
6981             /* They're both variables that are larger than bits */
6982             int s = size;
6983
6984             tlbl = newiTempLabel(NULL);
6985
6986             while(size--) {
6987               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6988               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6989
6990               if ( IC_TRUE(ifx) ) {
6991                 if(size) {
6992                   emitSKPZ;
6993                 
6994                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6995
6996                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6997                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6998                 } else {
6999                   emitSKPNZ;
7000
7001                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7002
7003
7004                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7005                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7006                 }
7007               } else {
7008                 emitSKPZ;
7009
7010                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7011
7012                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7013                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7014               }
7015               offset++;
7016             }
7017             if(s>1 && IC_TRUE(ifx)) {
7018               pic16_emitpLabel(tlbl->key);
7019               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7020             }
7021           }
7022         }
7023         /* mark the icode as generated */
7024         ifx->generated = 1;
7025         goto release ;
7026     }
7027
7028     /* if they are both bit variables */
7029     if (AOP_TYPE(left) == AOP_CRY &&
7030         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7031         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7032         if(AOP_TYPE(right) == AOP_LIT){
7033             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7034             if(lit == 0L){
7035                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7036                 pic16_emitcode("cpl","c");
7037             } else if(lit == 1L) {
7038                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7039             } else {
7040                 pic16_emitcode("clr","c");
7041             }
7042             /* AOP_TYPE(right) == AOP_CRY */
7043         } else {
7044             symbol *lbl = newiTempLabel(NULL);
7045             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7046             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7047             pic16_emitcode("cpl","c");
7048             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7049         }
7050         /* c = 1 if egal */
7051         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7052             pic16_outBitC(result);
7053             goto release ;
7054         }
7055         if (ifx) {
7056             genIfxJump (ifx,"c");
7057             goto release ;
7058         }
7059         /* if the result is used in an arithmetic operation
7060         then put the result in place */
7061         pic16_outBitC(result);
7062     } else {
7063       
7064       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7065       gencjne(left,right,result,ifx);
7066 /*
7067       if(ifx) 
7068         gencjne(left,right,newiTempLabel(NULL));
7069       else {
7070         if(IC_TRUE(ifx)->key)
7071           gencjne(left,right,IC_TRUE(ifx)->key);
7072         else
7073           gencjne(left,right,IC_FALSE(ifx)->key);
7074         ifx->generated = 1;
7075         goto release ;
7076       }
7077       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7078         pic16_aopPut(AOP(result),"a",0);
7079         goto release ;
7080       }
7081
7082       if (ifx) {
7083         genIfxJump (ifx,"a");
7084         goto release ;
7085       }
7086 */
7087       /* if the result is used in an arithmetic operation
7088          then put the result in place */
7089 /*
7090       if (AOP_TYPE(result) != AOP_CRY) 
7091         pic16_outAcc(result);
7092 */
7093       /* leave the result in acc */
7094     }
7095
7096 release:
7097     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7098     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7099     pic16_freeAsmop(result,NULL,ic,TRUE);
7100 }
7101 #endif
7102
7103 /*-----------------------------------------------------------------*/
7104 /* ifxForOp - returns the icode containing the ifx for operand     */
7105 /*-----------------------------------------------------------------*/
7106 static iCode *ifxForOp ( operand *op, iCode *ic )
7107 {
7108   FENTRY2;
7109
7110     /* if true symbol then needs to be assigned */
7111     if (IS_TRUE_SYMOP(op))
7112         return NULL ;
7113
7114     /* if this has register type condition and
7115     the next instruction is ifx with the same operand
7116     and live to of the operand is upto the ifx only then */
7117     if (ic->next
7118         && ic->next->op == IFX
7119         && IC_COND(ic->next)->key == op->key
7120         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7121         ) {
7122                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7123           return ic->next;
7124     }
7125
7126     /*
7127     if (ic->next &&
7128         ic->next->op == IFX &&
7129         IC_COND(ic->next)->key == op->key) {
7130       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7131       return ic->next;
7132     }
7133     */
7134
7135     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7136     if (ic->next &&
7137         ic->next->op == IFX)
7138       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7139
7140     if (ic->next &&
7141         ic->next->op == IFX &&
7142         IC_COND(ic->next)->key == op->key) {
7143       DEBUGpic16_emitcode ("; "," key is okay");
7144       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7145                            OP_SYMBOL(op)->liveTo,
7146                            ic->next->seq);
7147     }
7148
7149 #if 0
7150     /* the code below is completely untested
7151      * it just allows ulong2fs.c compile -- VR */
7152          
7153     ic = ic->next;
7154     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7155                                         __FILE__, __FUNCTION__, __LINE__);
7156         
7157     /* if this has register type condition and
7158     the next instruction is ifx with the same operand
7159     and live to of the operand is upto the ifx only then */
7160     if (ic->next &&
7161         ic->next->op == IFX &&
7162         IC_COND(ic->next)->key == op->key &&
7163         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7164         return ic->next;
7165
7166     if (ic->next &&
7167         ic->next->op == IFX &&
7168         IC_COND(ic->next)->key == op->key) {
7169       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7170       return ic->next;
7171     }
7172
7173     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7174                                         __FILE__, __FUNCTION__, __LINE__);
7175
7176 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7177 #endif
7178
7179     return NULL;
7180 }
7181 /*-----------------------------------------------------------------*/
7182 /* genAndOp - for && operation                                     */
7183 /*-----------------------------------------------------------------*/
7184 static void genAndOp (iCode *ic)
7185 {
7186   operand *left,*right, *result;
7187 /*     symbol *tlbl; */
7188
7189     FENTRY;
7190
7191     /* note here that && operations that are in an
7192     if statement are taken away by backPatchLabels
7193     only those used in arthmetic operations remain */
7194     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7195     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7196     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7197
7198     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7199
7200     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7201     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7202     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7203
7204     /* if both are bit variables */
7205 /*     if (AOP_TYPE(left) == AOP_CRY && */
7206 /*         AOP_TYPE(right) == AOP_CRY ) { */
7207 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7208 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7209 /*         pic16_outBitC(result); */
7210 /*     } else { */
7211 /*         tlbl = newiTempLabel(NULL); */
7212 /*         pic16_toBoolean(left);     */
7213 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7214 /*         pic16_toBoolean(right); */
7215 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7216 /*         pic16_outBitAcc(result); */
7217 /*     } */
7218
7219     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7220     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7221     pic16_freeAsmop(result,NULL,ic,TRUE);
7222 }
7223
7224
7225 /*-----------------------------------------------------------------*/
7226 /* genOrOp - for || operation                                      */
7227 /*-----------------------------------------------------------------*/
7228 /*
7229   tsd pic port -
7230   modified this code, but it doesn't appear to ever get called
7231 */
7232
7233 static void genOrOp (iCode *ic)
7234 {
7235   operand *left,*right, *result;
7236   symbol *tlbl;
7237
7238     FENTRY;  
7239
7240   /* note here that || operations that are in an
7241     if statement are taken away by backPatchLabels
7242     only those used in arthmetic operations remain */
7243     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7244     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7245     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7246
7247     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7248
7249     /* if both are bit variables */
7250     if (AOP_TYPE(left) == AOP_CRY &&
7251         AOP_TYPE(right) == AOP_CRY ) {
7252       pic16_emitcode("clrc","");
7253       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7254                AOP(left)->aopu.aop_dir,
7255                AOP(left)->aopu.aop_dir);
7256       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7257                AOP(right)->aopu.aop_dir,
7258                AOP(right)->aopu.aop_dir);
7259       pic16_emitcode("setc","");
7260
7261     } else {
7262         tlbl = newiTempLabel(NULL);
7263         pic16_toBoolean(left);
7264         emitSKPZ;
7265         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7266         pic16_toBoolean(right);
7267         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7268
7269         pic16_outBitAcc(result);
7270     }
7271
7272     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7273     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7274     pic16_freeAsmop(result,NULL,ic,TRUE);            
7275 }
7276
7277 /*-----------------------------------------------------------------*/
7278 /* isLiteralBit - test if lit == 2^n                               */
7279 /*-----------------------------------------------------------------*/
7280 static int isLiteralBit(unsigned long lit)
7281 {
7282     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7283     0x100L,0x200L,0x400L,0x800L,
7284     0x1000L,0x2000L,0x4000L,0x8000L,
7285     0x10000L,0x20000L,0x40000L,0x80000L,
7286     0x100000L,0x200000L,0x400000L,0x800000L,
7287     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7288     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7289     int idx;
7290     
7291     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7292     for(idx = 0; idx < 32; idx++)
7293         if(lit == pw[idx])
7294             return idx+1;
7295     return 0;
7296 }
7297
7298 /*-----------------------------------------------------------------*/
7299 /* continueIfTrue -                                                */
7300 /*-----------------------------------------------------------------*/
7301 static void continueIfTrue (iCode *ic)
7302 {
7303   FENTRY;
7304   if(IC_TRUE(ic))
7305     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7306   ic->generated = 1;
7307 }
7308
7309 /*-----------------------------------------------------------------*/
7310 /* jmpIfTrue -                                                     */
7311 /*-----------------------------------------------------------------*/
7312 static void jumpIfTrue (iCode *ic)
7313 {
7314   FENTRY;
7315   if(!IC_TRUE(ic))
7316     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7317   ic->generated = 1;
7318 }
7319
7320 /*-----------------------------------------------------------------*/
7321 /* jmpTrueOrFalse -                                                */
7322 /*-----------------------------------------------------------------*/
7323 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7324 {
7325   // ugly but optimized by peephole
7326   FENTRY;
7327   if(IC_TRUE(ic)){
7328     symbol *nlbl = newiTempLabel(NULL);
7329       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7330       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7331       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7332       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7333   } else {
7334     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7335     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7336   }
7337   ic->generated = 1;
7338 }
7339
7340 /*-----------------------------------------------------------------*/
7341 /* genAnd  - code for and                                          */
7342 /*-----------------------------------------------------------------*/
7343 static void genAnd (iCode *ic, iCode *ifx)
7344 {
7345   operand *left, *right, *result;
7346   int size, offset=0;  
7347   unsigned long lit = 0L;
7348   int bytelit = 0;
7349   resolvedIfx rIfx;
7350
7351     FENTRY;
7352     
7353   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7354   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7355   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7356
7357   resolveIfx(&rIfx,ifx);
7358
7359   /* if left is a literal & right is not then exchange them */
7360   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7361       AOP_NEEDSACC(left)) {
7362     operand *tmp = right ;
7363     right = left;
7364     left = tmp;
7365   }
7366
7367   /* if result = right then exchange them */
7368   if(pic16_sameRegs(AOP(result),AOP(right))){
7369     operand *tmp = right ;
7370     right = left;
7371     left = tmp;
7372   }
7373
7374   /* if right is bit then exchange them */
7375   if (AOP_TYPE(right) == AOP_CRY &&
7376       AOP_TYPE(left) != AOP_CRY){
7377     operand *tmp = right ;
7378     right = left;
7379     left = tmp;
7380   }
7381   if(AOP_TYPE(right) == AOP_LIT)
7382     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7383
7384   size = AOP_SIZE(result);
7385
7386   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7387
7388   // if(bit & yy)
7389   // result = bit & yy;
7390   if (AOP_TYPE(left) == AOP_CRY){
7391     // c = bit & literal;
7392     if(AOP_TYPE(right) == AOP_LIT){
7393       if(lit & 1) {
7394         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7395           // no change
7396           goto release;
7397         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7398       } else {
7399         // bit(result) = 0;
7400         if(size && (AOP_TYPE(result) == AOP_CRY)){
7401           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7402           goto release;
7403         }
7404         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7405           jumpIfTrue(ifx);
7406           goto release;
7407         }
7408         pic16_emitcode("clr","c");
7409       }
7410     } else {
7411       if (AOP_TYPE(right) == AOP_CRY){
7412         // c = bit & bit;
7413         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7414         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7415       } else {
7416         // c = bit & val;
7417         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7418         // c = lsb
7419         pic16_emitcode("rrc","a");
7420         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7421       }
7422     }
7423     // bit = c
7424     // val = c
7425     if(size)
7426       pic16_outBitC(result);
7427     // if(bit & ...)
7428     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7429       genIfxJump(ifx, "c");           
7430     goto release ;
7431   }
7432
7433   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7434   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7435   if((AOP_TYPE(right) == AOP_LIT) &&
7436      (AOP_TYPE(result) == AOP_CRY) &&
7437      (AOP_TYPE(left) != AOP_CRY)){
7438     int posbit = isLiteralBit(lit);
7439     /* left &  2^n */
7440     if(posbit){
7441       posbit--;
7442       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7443       // bit = left & 2^n
7444       if(size)
7445         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7446       // if(left &  2^n)
7447       else{
7448         if(ifx){
7449 /*
7450           if(IC_TRUE(ifx)) {
7451             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7452             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7453           } else {
7454             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7455             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7456           }
7457 */
7458         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7459         size = AOP_SIZE(left);
7460
7461         {
7462           int bp = posbit, ofs=0;
7463           
7464             while(bp > 7) {
7465               bp -= 8;
7466               ofs++;
7467             }
7468         
7469           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7470                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7471
7472         }
7473 /*
7474           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7475                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7476 */
7477           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7478           
7479           ifx->generated = 1;
7480         }
7481         goto release;
7482       }
7483     } else {
7484       symbol *tlbl = newiTempLabel(NULL);
7485       int sizel = AOP_SIZE(left);
7486
7487       if(size)
7488         emitSETC;
7489
7490       while(sizel--) {
7491         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7492
7493           /* patch provided by Aaron Colwell */
7494           if((posbit = isLiteralBit(bytelit)) != 0) {
7495               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7496                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7497                                                 (posbit-1),0, PO_GPR_REGISTER));
7498
7499               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7500 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7501           } else {
7502               if (bytelit == 0xff) {
7503                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7504                    * a peephole could optimize it out -- VR */
7505                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7506               } else {
7507                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7508                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7509               }
7510
7511               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7512                             pic16_popGetLabel(tlbl->key));
7513           }
7514         
7515 #if 0
7516           /* old code, left here for reference -- VR 09/2004 */
7517           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7518           // byte ==  2^n ?
7519           if((posbit = isLiteralBit(bytelit)) != 0)
7520             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7521           else{
7522             if(bytelit != 0x0FFL)
7523               pic16_emitcode("anl","a,%s",
7524                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7525             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7526           }
7527 #endif
7528         }
7529         offset++;
7530       }
7531       // bit = left & literal
7532       if(size) {
7533         emitCLRC;
7534         pic16_emitpLabel(tlbl->key);
7535       }
7536       // if(left & literal)
7537       else {
7538         if(ifx) {
7539           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7540           ifx->generated = 1;
7541         }
7542         pic16_emitpLabel(tlbl->key);
7543         goto release;
7544       }
7545     }
7546
7547     pic16_outBitC(result);
7548     goto release ;
7549   }
7550
7551   /* if left is same as result */
7552   if(pic16_sameRegs(AOP(result),AOP(left))){
7553     int know_W = -1;
7554     for(;size--; offset++,lit>>=8) {
7555       if(AOP_TYPE(right) == AOP_LIT){
7556         switch(lit & 0xff) {
7557         case 0x00:
7558           /*  and'ing with 0 has clears the result */
7559 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7560           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7561           break;
7562         case 0xff:
7563           /* and'ing with 0xff is a nop when the result and left are the same */
7564           break;
7565
7566         default:
7567           {
7568             int p = pic16_my_powof2( (~lit) & 0xff );
7569             if(p>=0) {
7570               /* only one bit is set in the literal, so use a bcf instruction */
7571 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7572               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7573
7574             } else {
7575               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7576               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7577               if(know_W != (lit&0xff))
7578                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7579               know_W = lit &0xff;
7580               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7581             }
7582           }    
7583         }
7584       } else {
7585         if (AOP_TYPE(left) == AOP_ACC) {
7586           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7587         } else {                    
7588           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7589           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7590
7591         }
7592       }
7593     }
7594
7595   } else {
7596     // left & result in different registers
7597     if(AOP_TYPE(result) == AOP_CRY){
7598       // result = bit
7599       // if(size), result in bit
7600       // if(!size && ifx), conditional oper: if(left & right)
7601       symbol *tlbl = newiTempLabel(NULL);
7602       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7603       if(size)
7604         pic16_emitcode("setb","c");
7605       while(sizer--){
7606         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7607         pic16_emitcode("anl","a,%s",
7608                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7609         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7610         offset++;
7611       }
7612       if(size){
7613         CLRC;
7614         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7615         pic16_outBitC(result);
7616       } else if(ifx)
7617         jmpTrueOrFalse(ifx, tlbl);
7618     } else {
7619       for(;(size--);offset++) {
7620         // normal case
7621         // result = left & right
7622         if(AOP_TYPE(right) == AOP_LIT){
7623           int t = (lit >> (offset*8)) & 0x0FFL;
7624           switch(t) { 
7625           case 0x00:
7626             pic16_emitcode("clrf","%s",
7627                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7628             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7629             break;
7630           case 0xff:
7631             pic16_emitcode("movf","%s,w",
7632                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7633             pic16_emitcode("movwf","%s",
7634                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7635             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7636             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7637             break;
7638           default:
7639             pic16_emitcode("movlw","0x%x",t);
7640             pic16_emitcode("andwf","%s,w",
7641                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7642             pic16_emitcode("movwf","%s",
7643                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7644               
7645             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7646             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7647             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7648           }
7649           continue;
7650         }
7651
7652         if (AOP_TYPE(left) == AOP_ACC) {
7653           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7654           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7655         } else {
7656           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7657           pic16_emitcode("andwf","%s,w",
7658                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7659           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7660           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7661         }
7662         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7663         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7664       }
7665     }
7666   }
7667
7668   release :
7669     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7670   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7671   pic16_freeAsmop(result,NULL,ic,TRUE);     
7672 }
7673
7674 /*-----------------------------------------------------------------*/
7675 /* genOr  - code for or                                            */
7676 /*-----------------------------------------------------------------*/
7677 static void genOr (iCode *ic, iCode *ifx)
7678 {
7679     operand *left, *right, *result;
7680     int size, offset=0;
7681     unsigned long lit = 0L;
7682
7683     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7684
7685     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7686     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7687     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7688
7689     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7690
7691     /* if left is a literal & right is not then exchange them */
7692     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7693         AOP_NEEDSACC(left)) {
7694         operand *tmp = right ;
7695         right = left;
7696         left = tmp;
7697     }
7698
7699     /* if result = right then exchange them */
7700     if(pic16_sameRegs(AOP(result),AOP(right))){
7701         operand *tmp = right ;
7702         right = left;
7703         left = tmp;
7704     }
7705
7706     /* if right is bit then exchange them */
7707     if (AOP_TYPE(right) == AOP_CRY &&
7708         AOP_TYPE(left) != AOP_CRY){
7709         operand *tmp = right ;
7710         right = left;
7711         left = tmp;
7712     }
7713
7714     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7715
7716     if(AOP_TYPE(right) == AOP_LIT)
7717         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7718
7719     size = AOP_SIZE(result);
7720
7721     // if(bit | yy)
7722     // xx = bit | yy;
7723     if (AOP_TYPE(left) == AOP_CRY){
7724         if(AOP_TYPE(right) == AOP_LIT){
7725             // c = bit & literal;
7726             if(lit){
7727                 // lit != 0 => result = 1
7728                 if(AOP_TYPE(result) == AOP_CRY){
7729                   if(size)
7730                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7731                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7732                   //     AOP(result)->aopu.aop_dir,
7733                   //     AOP(result)->aopu.aop_dir);
7734                     else if(ifx)
7735                         continueIfTrue(ifx);
7736                     goto release;
7737                 }
7738             } else {
7739                 // lit == 0 => result = left
7740                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7741                     goto release;
7742                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7743             }
7744         } else {
7745             if (AOP_TYPE(right) == AOP_CRY){
7746               if(pic16_sameRegs(AOP(result),AOP(left))){
7747                 // c = bit | bit;
7748                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7749                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7750                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7751
7752                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7753                          AOP(result)->aopu.aop_dir,
7754                          AOP(result)->aopu.aop_dir);
7755                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7756                          AOP(right)->aopu.aop_dir,
7757                          AOP(right)->aopu.aop_dir);
7758                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7759                          AOP(result)->aopu.aop_dir,
7760                          AOP(result)->aopu.aop_dir);
7761               } else {
7762                 if( AOP_TYPE(result) == AOP_ACC) {
7763                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7764                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7765                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7766                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7767
7768                 } else {
7769
7770                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7771                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7772                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7773                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7774
7775                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7776                                  AOP(result)->aopu.aop_dir,
7777                                  AOP(result)->aopu.aop_dir);
7778                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7779                                  AOP(right)->aopu.aop_dir,
7780                                  AOP(right)->aopu.aop_dir);
7781                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7782                                  AOP(left)->aopu.aop_dir,
7783                                  AOP(left)->aopu.aop_dir);
7784                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7785                                  AOP(result)->aopu.aop_dir,
7786                                  AOP(result)->aopu.aop_dir);
7787                 }
7788               }
7789             } else {
7790                 // c = bit | val;
7791                 symbol *tlbl = newiTempLabel(NULL);
7792                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7793
7794
7795                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7796                 if( AOP_TYPE(right) == AOP_ACC) {
7797                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7798                   emitSKPNZ;
7799                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7800                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7801                 }
7802
7803
7804
7805                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7806                     pic16_emitcode(";XXX setb","c");
7807                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7808                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7809                 pic16_toBoolean(right);
7810                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7811                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7812                     jmpTrueOrFalse(ifx, tlbl);
7813                     goto release;
7814                 } else {
7815                     CLRC;
7816                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7817                 }
7818             }
7819         }
7820         // bit = c
7821         // val = c
7822         if(size)
7823             pic16_outBitC(result);
7824         // if(bit | ...)
7825         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7826             genIfxJump(ifx, "c");           
7827         goto release ;
7828     }
7829
7830     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7831     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7832     if((AOP_TYPE(right) == AOP_LIT) &&
7833        (AOP_TYPE(result) == AOP_CRY) &&
7834        (AOP_TYPE(left) != AOP_CRY)){
7835         if(lit){
7836           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7837             // result = 1
7838             if(size)
7839                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7840             else 
7841                 continueIfTrue(ifx);
7842             goto release;
7843         } else {
7844           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7845             // lit = 0, result = boolean(left)
7846             if(size)
7847                 pic16_emitcode(";XXX setb","c");
7848             pic16_toBoolean(right);
7849             if(size){
7850                 symbol *tlbl = newiTempLabel(NULL);
7851                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7852                 CLRC;
7853                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7854             } else {
7855                 genIfxJump (ifx,"a");
7856                 goto release;
7857             }
7858         }
7859         pic16_outBitC(result);
7860         goto release ;
7861     }
7862
7863     /* if left is same as result */
7864     if(pic16_sameRegs(AOP(result),AOP(left))){
7865       int know_W = -1;
7866       for(;size--; offset++,lit>>=8) {
7867         if(AOP_TYPE(right) == AOP_LIT){
7868           if((lit & 0xff) == 0)
7869             /*  or'ing with 0 has no effect */
7870             continue;
7871           else {
7872             int p = pic16_my_powof2(lit & 0xff);
7873             if(p>=0) {
7874               /* only one bit is set in the literal, so use a bsf instruction */
7875               pic16_emitpcode(POC_BSF,
7876                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7877             } else {
7878               if(know_W != (lit & 0xff))
7879                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7880               know_W = lit & 0xff;
7881               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7882             }
7883                     
7884           }
7885         } else {
7886           if (AOP_TYPE(left) == AOP_ACC) {
7887             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7888             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7889           } else {                  
7890             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7891             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7892
7893             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7894             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
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 = max(AOP_SIZE(left),AOP_SIZE(right));
7907             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7908
7909
7910             if(size)
7911                 pic16_emitcode(";XXX setb","c");
7912             while(sizer--){
7913                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7914                 pic16_emitcode(";XXX orl","a,%s",
7915                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7916                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7917                 offset++;
7918             }
7919             if(size){
7920                 CLRC;
7921                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7922                 pic16_outBitC(result);
7923             } else if(ifx)
7924                 jmpTrueOrFalse(ifx, tlbl);
7925         } else for(;(size--);offset++){
7926           // normal case
7927           // result = left & right
7928           if(AOP_TYPE(right) == AOP_LIT){
7929             int t = (lit >> (offset*8)) & 0x0FFL;
7930             switch(t) { 
7931             case 0x00:
7932               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7933               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7934
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               break;
7940             default:
7941               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7942               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7943               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7944
7945               pic16_emitcode("movlw","0x%x",t);
7946               pic16_emitcode("iorwf","%s,w",
7947                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7948               pic16_emitcode("movwf","%s",
7949                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7950               
7951             }
7952             continue;
7953           }
7954
7955           // faster than result <- left, anl result,right
7956           // and better if result is SFR
7957           if (AOP_TYPE(left) == AOP_ACC) {
7958             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7959             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7960           } else {
7961             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7962             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7963
7964             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7965             pic16_emitcode("iorwf","%s,w",
7966                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7967           }
7968           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7969           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7970         }
7971     }
7972
7973 release :
7974     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7975     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7976     pic16_freeAsmop(result,NULL,ic,TRUE);     
7977 }
7978
7979 /*-----------------------------------------------------------------*/
7980 /* genXor - code for xclusive or                                   */
7981 /*-----------------------------------------------------------------*/
7982 static void genXor (iCode *ic, iCode *ifx)
7983 {
7984   operand *left, *right, *result;
7985   int size, offset=0;
7986   unsigned long lit = 0L;
7987
7988   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7989
7990   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7991   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7992   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7993
7994   /* if left is a literal & right is not ||
7995      if left needs acc & right does not */
7996   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7997       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
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   if(AOP_TYPE(right) == AOP_LIT)
8018     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8019
8020   size = AOP_SIZE(result);
8021
8022   // if(bit ^ yy)
8023   // xx = bit ^ yy;
8024   if (AOP_TYPE(left) == AOP_CRY){
8025     if(AOP_TYPE(right) == AOP_LIT){
8026       // c = bit & literal;
8027       if(lit>>1){
8028         // lit>>1  != 0 => result = 1
8029         if(AOP_TYPE(result) == AOP_CRY){
8030           if(size)
8031             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8032             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8033           else if(ifx)
8034             continueIfTrue(ifx);
8035           goto release;
8036         }
8037         pic16_emitcode("setb","c");
8038       } else{
8039         // lit == (0 or 1)
8040         if(lit == 0){
8041           // lit == 0, result = left
8042           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8043             goto release;
8044           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8045         } else{
8046           // lit == 1, result = not(left)
8047           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8048             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8049             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8050             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8051             goto release;
8052           } else {
8053             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8054             pic16_emitcode("cpl","c");
8055           }
8056         }
8057       }
8058
8059     } else {
8060       // right != literal
8061       symbol *tlbl = newiTempLabel(NULL);
8062       if (AOP_TYPE(right) == AOP_CRY){
8063         // c = bit ^ bit;
8064         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8065       }
8066       else{
8067         int sizer = AOP_SIZE(right);
8068         // c = bit ^ val
8069         // if val>>1 != 0, result = 1
8070         pic16_emitcode("setb","c");
8071         while(sizer){
8072           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8073           if(sizer == 1)
8074             // test the msb of the lsb
8075             pic16_emitcode("anl","a,#0xfe");
8076           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8077           sizer--;
8078         }
8079         // val = (0,1)
8080         pic16_emitcode("rrc","a");
8081       }
8082       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8083       pic16_emitcode("cpl","c");
8084       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8085     }
8086     // bit = c
8087     // val = c
8088     if(size)
8089       pic16_outBitC(result);
8090     // if(bit | ...)
8091     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8092       genIfxJump(ifx, "c");           
8093     goto release ;
8094   }
8095
8096   if(pic16_sameRegs(AOP(result),AOP(left))){
8097     /* if left is same as result */
8098     for(;size--; offset++) {
8099       if(AOP_TYPE(right) == AOP_LIT){
8100         int t  = (lit >> (offset*8)) & 0x0FFL;
8101         if(t == 0x00L)
8102           continue;
8103         else
8104           if (IS_AOP_PREG(left)) {
8105             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8106             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8107             pic16_aopPut(AOP(result),"a",offset);
8108           } else {
8109             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8110             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8111             pic16_emitcode("xrl","%s,%s",
8112                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8113                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8114           }
8115       } else {
8116         if (AOP_TYPE(left) == AOP_ACC)
8117           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8118         else {
8119           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8120           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8121 /*
8122           if (IS_AOP_PREG(left)) {
8123             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8124             pic16_aopPut(AOP(result),"a",offset);
8125           } else
8126             pic16_emitcode("xrl","%s,a",
8127                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8128 */
8129         }
8130       }
8131     }
8132   } else {
8133     // left & result in different registers
8134     if(AOP_TYPE(result) == AOP_CRY){
8135       // result = bit
8136       // if(size), result in bit
8137       // if(!size && ifx), conditional oper: if(left ^ right)
8138       symbol *tlbl = newiTempLabel(NULL);
8139       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8140       if(size)
8141         pic16_emitcode("setb","c");
8142       while(sizer--){
8143         if((AOP_TYPE(right) == AOP_LIT) &&
8144            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8145           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8146         } else {
8147           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8148           pic16_emitcode("xrl","a,%s",
8149                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8150         }
8151         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8152         offset++;
8153       }
8154       if(size){
8155         CLRC;
8156         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8157         pic16_outBitC(result);
8158       } else if(ifx)
8159         jmpTrueOrFalse(ifx, tlbl);
8160     } else for(;(size--);offset++){
8161       // normal case
8162       // result = left & right
8163       if(AOP_TYPE(right) == AOP_LIT){
8164         int t = (lit >> (offset*8)) & 0x0FFL;
8165         switch(t) { 
8166         case 0x00:
8167           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8168           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8169           pic16_emitcode("movf","%s,w",
8170                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8171           pic16_emitcode("movwf","%s",
8172                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8173           break;
8174         case 0xff:
8175           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8176           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8177           pic16_emitcode("comf","%s,w",
8178                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8179           pic16_emitcode("movwf","%s",
8180                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8181           break;
8182         default:
8183           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8184           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8185           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8186           pic16_emitcode("movlw","0x%x",t);
8187           pic16_emitcode("xorwf","%s,w",
8188                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8189           pic16_emitcode("movwf","%s",
8190                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8191
8192         }
8193         continue;
8194       }
8195
8196       // faster than result <- left, anl result,right
8197       // and better if result is SFR
8198       if (AOP_TYPE(left) == AOP_ACC) {
8199         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8200         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8201       } else {
8202         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8203         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8204         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8205         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8206       }
8207       if ( AOP_TYPE(result) != AOP_ACC){
8208         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8209         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8210       }
8211     }
8212   }
8213
8214   release :
8215     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8216   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8217   pic16_freeAsmop(result,NULL,ic,TRUE);     
8218 }
8219
8220 /*-----------------------------------------------------------------*/
8221 /* genInline - write the inline code out                           */
8222 /*-----------------------------------------------------------------*/
8223 static void genInline (iCode *ic)
8224 {
8225   char *buffer, *bp, *bp1;
8226   char *cbuf;
8227     
8228         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8229
8230         _G.inLine += (!options.asmpeep);
8231
8232         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8233         strcpy(buffer,IC_INLINE(ic));
8234         
8235         while((bp1=strstr(bp, "\\n"))) {
8236           *bp1++ = '\n';
8237           *bp1++ = ' ';
8238           bp = bp1;
8239         }
8240         bp = bp1 = buffer;
8241
8242         cbuf = Safe_strdup( buffer );
8243
8244         if(asmInlineMap)
8245         {
8246           symbol *sym;
8247           char *s;
8248           int cblen;
8249
8250             cbuf = Safe_strdup(buffer);
8251             cblen = strlen(buffer)+1;
8252             memset(cbuf, 0, cblen);
8253
8254             bp = buffer;
8255             bp1 = cbuf;
8256             while(*bp) {
8257               if(*bp != '%')*bp1++ = *bp++;
8258               else {
8259                 int i;
8260
8261                   bp++;
8262                   i = *bp - '0';
8263                   if(i>elementsInSet(asmInlineMap))break;
8264                   
8265                   bp++;
8266                   s = indexSet(asmInlineMap, i);
8267                   DEBUGpc("searching symbol s = `%s'", s);
8268                   sym = findSym(SymbolTab, NULL, s);
8269
8270                   if(sym->reqv) {
8271                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8272                   } else {
8273                     strcat(bp1, sym->rname);
8274                   }
8275                   
8276                   while(*bp1)bp1++;
8277               }
8278               
8279               if(strlen(bp1) > cblen - 16) {
8280                 int i = strlen(cbuf);
8281                 cblen += 50;
8282                 cbuf = realloc(cbuf, cblen);
8283                 memset(cbuf+i, 0, 50);
8284                 bp1 = cbuf + i;
8285               }
8286             }
8287             
8288             free(buffer);
8289             buffer = Safe_strdup( cbuf );
8290             free(cbuf);
8291             
8292             bp = bp1 = buffer;
8293         }
8294
8295         /* emit each line as a code */
8296         while (*bp) {
8297                 if (*bp == '\n') {
8298                         *bp++ = '\0';
8299
8300                         if(*bp1)
8301                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8302                         bp1 = bp;
8303                 } else {
8304                         if (*bp == ':') {
8305                                 bp++;
8306                                 *bp = '\0';
8307                                 bp++;
8308
8309                                 /* print label, use this special format with NULL directive
8310                                  * to denote that the argument should not be indented with tab */
8311                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8312                                 bp1 = bp;
8313                         } else
8314                                 bp++;
8315                 }
8316         }
8317
8318         if ((bp1 != bp) && *bp1)
8319                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8320
8321
8322     Safe_free(buffer);
8323
8324     _G.inLine -= (!options.asmpeep);
8325 }
8326
8327 /*-----------------------------------------------------------------*/
8328 /* genRRC - rotate right with carry                                */
8329 /*-----------------------------------------------------------------*/
8330 static void genRRC (iCode *ic)
8331 {
8332   operand *left , *result ;
8333   int size, offset = 0, same;
8334
8335   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8336
8337   /* rotate right with carry */
8338   left = IC_LEFT(ic);
8339   result=IC_RESULT(ic);
8340   pic16_aopOp (left,ic,FALSE);
8341   pic16_aopOp (result,ic,TRUE);
8342
8343   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8344
8345   same = pic16_sameRegs(AOP(result),AOP(left));
8346
8347   size = AOP_SIZE(result);    
8348
8349   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8350
8351   /* get the lsb and put it into the carry */
8352   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8353
8354   offset = 0 ;
8355
8356   while(size--) {
8357
8358     if(same) {
8359       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8360     } else {
8361       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8362       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8363     }
8364
8365     offset++;
8366   }
8367
8368   pic16_freeAsmop(left,NULL,ic,TRUE);
8369   pic16_freeAsmop(result,NULL,ic,TRUE);
8370 }
8371
8372 /*-----------------------------------------------------------------*/
8373 /* genRLC - generate code for rotate left with carry               */
8374 /*-----------------------------------------------------------------*/
8375 static void genRLC (iCode *ic)
8376 {    
8377   operand *left , *result ;
8378   int size, offset = 0;
8379   int same;
8380
8381   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8382   /* rotate right with carry */
8383   left = IC_LEFT(ic);
8384   result=IC_RESULT(ic);
8385   pic16_aopOp (left,ic,FALSE);
8386   pic16_aopOp (result,ic,TRUE);
8387
8388   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8389
8390   same = pic16_sameRegs(AOP(result),AOP(left));
8391
8392   /* move it to the result */
8393   size = AOP_SIZE(result);    
8394
8395   /* get the msb and put it into the carry */
8396   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8397
8398   offset = 0 ;
8399
8400   while(size--) {
8401
8402     if(same) {
8403       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8404     } else {
8405       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8406       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8407     }
8408
8409     offset++;
8410   }
8411
8412
8413   pic16_freeAsmop(left,NULL,ic,TRUE);
8414   pic16_freeAsmop(result,NULL,ic,TRUE);
8415 }
8416
8417
8418 /* gpasm can get the highest order bit with HIGH/UPPER
8419  * so the following probably is not needed -- VR */
8420  
8421 /*-----------------------------------------------------------------*/
8422 /* genGetHbit - generates code get highest order bit               */
8423 /*-----------------------------------------------------------------*/
8424 static void genGetHbit (iCode *ic)
8425 {
8426     operand *left, *result;
8427     left = IC_LEFT(ic);
8428     result=IC_RESULT(ic);
8429     pic16_aopOp (left,ic,FALSE);
8430     pic16_aopOp (result,ic,FALSE);
8431
8432     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8433     /* get the highest order byte into a */
8434     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8435     if(AOP_TYPE(result) == AOP_CRY){
8436         pic16_emitcode("rlc","a");
8437         pic16_outBitC(result);
8438     }
8439     else{
8440         pic16_emitcode("rl","a");
8441         pic16_emitcode("anl","a,#0x01");
8442         pic16_outAcc(result);
8443     }
8444
8445
8446     pic16_freeAsmop(left,NULL,ic,TRUE);
8447     pic16_freeAsmop(result,NULL,ic,TRUE);
8448 }
8449
8450 #if 0
8451 /*-----------------------------------------------------------------*/
8452 /* AccRol - rotate left accumulator by known count                 */
8453 /*-----------------------------------------------------------------*/
8454 static void AccRol (int shCount)
8455 {
8456     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8457     shCount &= 0x0007;              // shCount : 0..7
8458     switch(shCount){
8459         case 0 :
8460             break;
8461         case 1 :
8462             pic16_emitcode("rl","a");
8463             break;
8464         case 2 :
8465             pic16_emitcode("rl","a");
8466             pic16_emitcode("rl","a");
8467             break;
8468         case 3 :
8469             pic16_emitcode("swap","a");
8470             pic16_emitcode("rr","a");
8471             break;
8472         case 4 :
8473             pic16_emitcode("swap","a");
8474             break;
8475         case 5 :
8476             pic16_emitcode("swap","a");
8477             pic16_emitcode("rl","a");
8478             break;
8479         case 6 :
8480             pic16_emitcode("rr","a");
8481             pic16_emitcode("rr","a");
8482             break;
8483         case 7 :
8484             pic16_emitcode("rr","a");
8485             break;
8486     }
8487 }
8488 #endif
8489
8490 /*-----------------------------------------------------------------*/
8491 /* AccLsh - left shift accumulator by known count                  */
8492 /*-----------------------------------------------------------------*/
8493 static void AccLsh (int shCount)
8494 {
8495         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8496         switch(shCount){
8497                 case 0 :
8498                         return;
8499                         break;
8500                 case 1 :
8501                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8502                         break;
8503                 case 2 :
8504                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8505                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8506                         break;
8507                 case 3 :
8508                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8509                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8510                         break;
8511                 case 4 :
8512                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8513                         break;
8514                 case 5 :
8515                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8516                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8517                         break;
8518                 case 6 :
8519                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8520                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8521                         break;
8522                 case 7 :
8523                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8524                         break;
8525         }
8526
8527         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8528 }
8529
8530 /*-----------------------------------------------------------------*/
8531 /* AccRsh - right shift accumulator by known count                 */
8532 /*-----------------------------------------------------------------*/
8533 static void AccRsh (int shCount, int andmask)
8534 {
8535         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8536         switch(shCount){
8537                 case 0 :
8538                         return; break;
8539                 case 1 :
8540                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8541                         break;
8542                 case 2 :
8543                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8544                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8545                         break;
8546                 case 3 :
8547                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8548                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8549                         break;
8550                 case 4 :
8551                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8552                         break;
8553                 case 5 :
8554                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8555                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8556                         break;
8557                 case 6 :
8558                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8559                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8560                         break;
8561                 case 7 :
8562                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8563                         break;
8564         }
8565         
8566         if(andmask)
8567                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8568         else
8569                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8570 }
8571
8572 #if 0
8573 /*-----------------------------------------------------------------*/
8574 /* AccSRsh - signed right shift accumulator by known count                 */
8575 /*-----------------------------------------------------------------*/
8576 static void AccSRsh (int shCount)
8577 {
8578     symbol *tlbl ;
8579     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8580     if(shCount != 0){
8581         if(shCount == 1){
8582             pic16_emitcode("mov","c,acc.7");
8583             pic16_emitcode("rrc","a");
8584         } else if(shCount == 2){
8585             pic16_emitcode("mov","c,acc.7");
8586             pic16_emitcode("rrc","a");
8587             pic16_emitcode("mov","c,acc.7");
8588             pic16_emitcode("rrc","a");
8589         } else {
8590             tlbl = newiTempLabel(NULL);
8591             /* rotate right accumulator */
8592             AccRol(8 - shCount);
8593             /* and kill the higher order bits */
8594             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8595             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8596             pic16_emitcode("orl","a,#0x%02x",
8597                      (unsigned char)~SRMask[shCount]);
8598             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8599         }
8600     }
8601 }
8602 #endif
8603
8604 /*-----------------------------------------------------------------*/
8605 /* shiftR1Left2Result - shift right one byte from left to result   */
8606 /*-----------------------------------------------------------------*/
8607 static void shiftR1Left2ResultSigned (operand *left, int offl,
8608                                 operand *result, int offr,
8609                                 int shCount)
8610 {
8611   int same;
8612
8613   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8614
8615   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8616
8617   switch(shCount) {
8618   case 1:
8619     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8620     if(same) 
8621       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8622     else {
8623       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8624       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8625     }
8626
8627     break;
8628   case 2:
8629
8630     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8631     if(same) 
8632       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8633     else {
8634       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8635       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8636     }
8637     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8638     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8639
8640     break;
8641
8642   case 3:
8643     if(same)
8644       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8645     else {
8646       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8647       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8648     }
8649
8650     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8651     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8652     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8653
8654     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8655     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8656
8657     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8658     break;
8659
8660   case 4:
8661     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8662     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8663     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8664     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8665     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8666     break;
8667   case 5:
8668     if(same) {
8669       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8670     } else {
8671       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8672       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8673     }
8674     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8675     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8676     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8677     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8678     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8679     break;
8680
8681   case 6:
8682     if(same) {
8683       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8684       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8685       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8686       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8687       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8688       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8689     } else {
8690       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8691       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8692       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8693       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8694       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8695     }
8696     break;
8697
8698   case 7:
8699     if(same) {
8700       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8701       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8702       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8703       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8704     } else {
8705       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8706       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8707       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8708     }
8709
8710   default:
8711     break;
8712   }
8713 }
8714
8715 /*-----------------------------------------------------------------*/
8716 /* shiftR1Left2Result - shift right one byte from left to result   */
8717 /*-----------------------------------------------------------------*/
8718 static void shiftR1Left2Result (operand *left, int offl,
8719                                 operand *result, int offr,
8720                                 int shCount, int sign)
8721 {
8722   int same;
8723
8724   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8725
8726   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8727
8728   /* Copy the msb into the carry if signed. */
8729   if(sign) {
8730     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8731     return;
8732   }
8733
8734
8735
8736   switch(shCount) {
8737   case 1:
8738     emitCLRC;
8739     if(same) 
8740       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8741     else {
8742       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8743       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8744     }
8745     break;
8746   case 2:
8747     emitCLRC;
8748     if(same) {
8749       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8750     } else {
8751       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8752       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8753     }
8754     emitCLRC;
8755     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8756
8757     break;
8758   case 3:
8759     if(same)
8760       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8761     else {
8762       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8763       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8764     }
8765
8766     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8767     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8768     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8769     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8770     break;
8771       
8772   case 4:
8773     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8774     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8775     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8776     break;
8777
8778   case 5:
8779     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8780     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8781     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8782     //emitCLRC;
8783     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8784
8785     break;
8786   case 6:
8787
8788     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8789     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8790     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8791     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8792     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8793     break;
8794
8795   case 7:
8796
8797     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8798     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8799     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8800
8801     break;
8802
8803   default:
8804     break;
8805   }
8806 }
8807
8808 /*-----------------------------------------------------------------*/
8809 /* shiftL1Left2Result - shift left one byte from left to result    */
8810 /*-----------------------------------------------------------------*/
8811 static void shiftL1Left2Result (operand *left, int offl,
8812                                 operand *result, int offr, int shCount)
8813 {
8814   int same;
8815
8816   //    char *l;
8817   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8818
8819   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8820   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8821     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8822     //    MOVA(l);
8823     /* shift left accumulator */
8824     //AccLsh(shCount); // don't comment out just yet...
8825   //    pic16_aopPut(AOP(result),"a",offr);
8826
8827   switch(shCount) {
8828   case 1:
8829     /* Shift left 1 bit position */
8830     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8831     if(same) {
8832       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8833     } else {
8834       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8835       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8836     }
8837     break;
8838   case 2:
8839     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8840     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8841     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8842     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8843     break;
8844   case 3:
8845     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8846     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8847     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8848     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8849     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8850     break;
8851   case 4:
8852     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8853     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8854     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8855     break;
8856   case 5:
8857     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8858     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8859     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8860     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8861     break;
8862   case 6:
8863     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8864     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8865     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8866     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8867     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8868     break;
8869   case 7:
8870     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8871     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8872     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8873     break;
8874
8875   default:
8876     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8877   }
8878
8879 }
8880
8881 /*-----------------------------------------------------------------*/
8882 /* movLeft2Result - move byte from left to result                  */
8883 /*-----------------------------------------------------------------*/
8884 static void movLeft2Result (operand *left, int offl,
8885                             operand *result, int offr)
8886 {
8887   char *l;
8888   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8889   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8890     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8891
8892     if (*l == '@' && (IS_AOP_PREG(result))) {
8893       pic16_emitcode("mov","a,%s",l);
8894       pic16_aopPut(AOP(result),"a",offr);
8895     } else {
8896       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8897       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8898     }
8899   }
8900 }
8901
8902 /*-----------------------------------------------------------------*/
8903 /* shiftL2Left2Result - shift left two bytes from left to result   */
8904 /*-----------------------------------------------------------------*/
8905 static void shiftL2Left2Result (operand *left, int offl,
8906                                 operand *result, int offr, int shCount)
8907 {
8908   int same = pic16_sameRegs(AOP(result), AOP(left));
8909   int i;
8910
8911   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8912
8913   if (same && (offl != offr)) { // shift bytes
8914     if (offr > offl) {
8915        for(i=1;i>-1;i--) {
8916          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8917          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8918        }
8919     } else { // just treat as different later on
8920                 same = 0;
8921     }
8922   }
8923
8924   if(same) {
8925     switch(shCount) {
8926     case 0:
8927       break;
8928     case 1:
8929     case 2:
8930     case 3:
8931
8932       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8933       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8934       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8935
8936       while(--shCount) {
8937                 emitCLRC;
8938                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8939                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8940       }
8941
8942       break;
8943     case 4:
8944     case 5:
8945       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8946       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8947       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8948       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8949       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8950       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8951       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8952       if(shCount >=5) {
8953                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8954                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8955       }
8956       break;
8957     case 6:
8958       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8959       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8960       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8961       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8962       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8963       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8964       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8965       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8966       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8967       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8968       break;
8969     case 7:
8970       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8971       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8972       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8973       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8974       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8975     }
8976
8977   } else {
8978     switch(shCount) {
8979     case 0:
8980       break;
8981     case 1:
8982     case 2:
8983     case 3:
8984       /* note, use a mov/add for the shift since the mov has a
8985          chance of getting optimized out */
8986       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8987       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8988       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8989       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8990       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8991
8992       while(--shCount) {
8993                 emitCLRC;
8994                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8995                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8996       }
8997       break;
8998
8999     case 4:
9000     case 5:
9001       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9002       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9003       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9004       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9005       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9006       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9007       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9008       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9009
9010
9011       if(shCount == 5) {
9012                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9013                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9014       }
9015       break;
9016     case 6:
9017       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9018       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9019       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9020       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9021
9022       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9023       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9024       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9025       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9026       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9027       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9028       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9029       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9030       break;
9031     case 7:
9032       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9033       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9034       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9035       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9036       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9037     }
9038   }
9039
9040 }
9041 /*-----------------------------------------------------------------*/
9042 /* shiftR2Left2Result - shift right two bytes from left to result  */
9043 /*-----------------------------------------------------------------*/
9044 static void shiftR2Left2Result (operand *left, int offl,
9045                                 operand *result, int offr,
9046                                 int shCount, int sign)
9047 {
9048   int same = pic16_sameRegs(AOP(result), AOP(left));
9049   int i;
9050   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9051
9052   if (same && (offl != offr)) { // shift right bytes
9053     if (offr < offl) {
9054        for(i=0;i<2;i++) {
9055          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9056          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9057        }
9058     } else { // just treat as different later on
9059                 same = 0;
9060     }
9061   }
9062
9063   switch(shCount) {
9064   case 0:
9065     break;
9066   case 1:
9067   case 2:
9068   case 3:
9069     if(sign)
9070       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9071     else
9072       emitCLRC;
9073
9074     if(same) {
9075       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9076       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9077     } else {
9078       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9079       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9080       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9081       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9082     }
9083
9084     while(--shCount) {
9085       if(sign)
9086                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9087       else
9088                 emitCLRC;
9089       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9090       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9091     }
9092     break;
9093   case 4:
9094   case 5:
9095     if(same) {
9096
9097       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9098       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9099       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9100
9101       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9102       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9103       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9104       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9105     } else {
9106       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9107       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9108       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9109
9110       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9111       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9112       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9113       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9114       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9115     }
9116
9117     if(shCount >=5) {
9118       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9119       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9120     }
9121
9122     if(sign) {
9123       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9124       pic16_emitpcode(POC_BTFSC, 
9125                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9126       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9127     }
9128
9129     break;
9130
9131   case 6:
9132     if(same) {
9133
9134       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9135       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9136
9137       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9138       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9139       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9140       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9141       if(sign) {
9142         pic16_emitpcode(POC_BTFSC, 
9143                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9144         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9145       }
9146       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9147       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9148       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9149       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9150     } else {
9151       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9152       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9153       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9154       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9155       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9156       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9157       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9158       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9159       if(sign) {
9160         pic16_emitpcode(POC_BTFSC, 
9161                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9162         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9163       }
9164       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9165       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9166
9167         
9168     }
9169
9170     break;
9171   case 7:
9172     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9173     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9174     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9175     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9176     if(sign) {
9177       emitSKPNC;
9178       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9179     } else 
9180       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9181   }
9182 }
9183
9184
9185 /*-----------------------------------------------------------------*/
9186 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9187 /*-----------------------------------------------------------------*/
9188 static void shiftLLeftOrResult (operand *left, int offl,
9189                                 operand *result, int offr, int shCount)
9190 {
9191     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9192
9193     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9194     /* shift left accumulator */
9195     AccLsh(shCount);
9196     /* or with result */
9197     /* back to result */
9198     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9199 }
9200
9201 /*-----------------------------------------------------------------*/
9202 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9203 /*-----------------------------------------------------------------*/
9204 static void shiftRLeftOrResult (operand *left, int offl,
9205                                 operand *result, int offr, int shCount)
9206 {
9207     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9208     
9209     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9210     /* shift right accumulator */
9211     AccRsh(shCount, 1);
9212     /* or with result */
9213     /* back to result */
9214     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9215 }
9216
9217 /*-----------------------------------------------------------------*/
9218 /* genlshOne - left shift a one byte quantity by known count       */
9219 /*-----------------------------------------------------------------*/
9220 static void genlshOne (operand *result, operand *left, int shCount)
9221 {       
9222     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9223     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9224 }
9225
9226 /*-----------------------------------------------------------------*/
9227 /* genlshTwo - left shift two bytes by known amount != 0           */
9228 /*-----------------------------------------------------------------*/
9229 static void genlshTwo (operand *result,operand *left, int shCount)
9230 {
9231     int size;
9232     
9233     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9234     size = pic16_getDataSize(result);
9235
9236     /* if shCount >= 8 */
9237     if (shCount >= 8) {
9238         shCount -= 8 ;
9239
9240         if (size > 1){
9241             if (shCount)
9242                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9243             else 
9244                 movLeft2Result(left, LSB, result, MSB16);
9245         }
9246         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9247     }
9248
9249     /*  1 <= shCount <= 7 */
9250     else {  
9251         if(size == 1)
9252             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9253         else 
9254             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9255     }
9256 }
9257
9258 /*-----------------------------------------------------------------*/
9259 /* shiftLLong - shift left one long from left to result            */
9260 /* offr = LSB or MSB16                                             */
9261 /*-----------------------------------------------------------------*/
9262 static void shiftLLong (operand *left, operand *result, int offr )
9263 {
9264     int size = AOP_SIZE(result);
9265     int same = pic16_sameRegs(AOP(left),AOP(result));
9266         int i;
9267
9268     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9269
9270         if (same && (offr == MSB16)) { //shift one byte
9271                 for(i=size-1;i>=MSB16;i--) {
9272                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9273                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9274                 }
9275         } else {
9276                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9277         }
9278         
9279     if (size > LSB+offr ){
9280                 if (same) {
9281                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9282                 } else {
9283                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9284                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9285                 }
9286          }
9287
9288     if(size > MSB16+offr){
9289                 if (same) {
9290                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9291                 } else {
9292                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9293                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9294                 }
9295     }
9296
9297     if(size > MSB24+offr){
9298                 if (same) {
9299                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9300                 } else {
9301                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9302                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9303                 }
9304     }
9305
9306     if(size > MSB32+offr){
9307                 if (same) {
9308                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9309                 } else {
9310                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9311                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9312                 }
9313     }
9314     if(offr != LSB)
9315                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9316
9317 }
9318
9319 /*-----------------------------------------------------------------*/
9320 /* genlshFour - shift four byte by a known amount != 0             */
9321 /*-----------------------------------------------------------------*/
9322 static void genlshFour (operand *result, operand *left, int shCount)
9323 {
9324     int size;
9325
9326     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9327     size = AOP_SIZE(result);
9328
9329     /* if shifting more that 3 bytes */
9330     if (shCount >= 24 ) {
9331         shCount -= 24;
9332         if (shCount)
9333             /* lowest order of left goes to the highest
9334             order of the destination */
9335             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9336         else
9337             movLeft2Result(left, LSB, result, MSB32);
9338
9339                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9340                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9341                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9342
9343         return;
9344     }
9345
9346     /* more than two bytes */
9347     else if ( shCount >= 16 ) {
9348         /* lower order two bytes goes to higher order two bytes */
9349         shCount -= 16;
9350         /* if some more remaining */
9351         if (shCount)
9352             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9353         else {
9354             movLeft2Result(left, MSB16, result, MSB32);
9355             movLeft2Result(left, LSB, result, MSB24);
9356         }
9357                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9358                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9359         return;
9360     }    
9361
9362     /* if more than 1 byte */
9363     else if ( shCount >= 8 ) {
9364         /* lower order three bytes goes to higher order  three bytes */
9365         shCount -= 8;
9366         if(size == 2){
9367             if(shCount)
9368                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9369             else
9370                 movLeft2Result(left, LSB, result, MSB16);
9371         }
9372         else{   /* size = 4 */
9373             if(shCount == 0){
9374                 movLeft2Result(left, MSB24, result, MSB32);
9375                 movLeft2Result(left, MSB16, result, MSB24);
9376                 movLeft2Result(left, LSB, result, MSB16);
9377                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9378             }
9379             else if(shCount == 1)
9380                 shiftLLong(left, result, MSB16);
9381             else{
9382                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9383                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9384                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9385                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9386             }
9387         }
9388     }
9389
9390     /* 1 <= shCount <= 7 */
9391     else if(shCount <= 3)
9392     { 
9393         shiftLLong(left, result, LSB);
9394         while(--shCount >= 1)
9395             shiftLLong(result, result, LSB);
9396     }
9397     /* 3 <= shCount <= 7, optimize */
9398     else{
9399         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9400         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9401         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9402     }
9403 }
9404
9405 /*-----------------------------------------------------------------*/
9406 /* genLeftShiftLiteral - left shifting by known count              */
9407 /*-----------------------------------------------------------------*/
9408 void pic16_genLeftShiftLiteral (operand *left,
9409                                  operand *right,
9410                                  operand *result,
9411                                  iCode *ic)
9412 {    
9413     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9414     int size;
9415
9416     FENTRY;
9417     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9418     pic16_freeAsmop(right,NULL,ic,TRUE);
9419
9420     pic16_aopOp(left,ic,FALSE);
9421     pic16_aopOp(result,ic,TRUE);
9422
9423     size = getSize(operandType(result));
9424
9425 #if VIEW_SIZE
9426     pic16_emitcode("; shift left ","result %d, left %d",size,
9427              AOP_SIZE(left));
9428 #endif
9429
9430     /* I suppose that the left size >= result size */
9431     if(shCount == 0){
9432         while(size--){
9433             movLeft2Result(left, size, result, size);
9434         }
9435     }
9436
9437     else if(shCount >= (size * 8))
9438         while(size--)
9439             pic16_aopPut(AOP(result),zero,size);
9440     else{
9441         switch (size) {
9442             case 1:
9443                 genlshOne (result,left,shCount);
9444                 break;
9445
9446             case 2:
9447             case 3:
9448                 genlshTwo (result,left,shCount);
9449                 break;
9450
9451             case 4:
9452                 genlshFour (result,left,shCount);
9453                 break;
9454         }
9455     }
9456     pic16_freeAsmop(left,NULL,ic,TRUE);
9457     pic16_freeAsmop(result,NULL,ic,TRUE);
9458 }
9459
9460 /*-----------------------------------------------------------------*
9461  * genMultiAsm - repeat assembly instruction for size of register.
9462  * if endian == 1, then the high byte (i.e base address + size of 
9463  * register) is used first else the low byte is used first;
9464  *-----------------------------------------------------------------*/
9465 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9466 {
9467
9468   int offset = 0;
9469
9470   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9471
9472   if(!reg)
9473     return;
9474
9475   if(!endian) {
9476     endian = 1;
9477   } else {
9478     endian = -1;
9479     offset = size-1;
9480   }
9481
9482   while(size--) {
9483     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9484     offset += endian;
9485   }
9486
9487 }
9488
9489 #if !(USE_GENERIC_SIGNED_SHIFT)
9490 /*-----------------------------------------------------------------*/
9491 /* genLeftShift - generates code for left shifting                 */
9492 /*-----------------------------------------------------------------*/
9493 static void genLeftShift (iCode *ic)
9494 {
9495   operand *left,*right, *result;
9496   int size, offset;
9497 //  char *l;
9498   symbol *tlbl , *tlbl1;
9499   pCodeOp *pctemp;
9500
9501   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9502
9503   right = IC_RIGHT(ic);
9504   left  = IC_LEFT(ic);
9505   result = IC_RESULT(ic);
9506
9507   pic16_aopOp(right,ic,FALSE);
9508
9509   /* if the shift count is known then do it 
9510      as efficiently as possible */
9511   if (AOP_TYPE(right) == AOP_LIT) {
9512     pic16_genLeftShiftLiteral (left,right,result,ic);
9513     return ;
9514   }
9515
9516   /* shift count is unknown then we have to form
9517    * a loop. Get the loop count in WREG : Note: we take
9518    * only the lower order byte since shifting
9519    * more than 32 bits make no sense anyway, ( the
9520    * largest size of an object can be only 32 bits ) */
9521   
9522   pic16_aopOp(left,ic,FALSE);
9523   pic16_aopOp(result,ic,FALSE);
9524
9525   /* now move the left to the result if they are not the
9526    * same, and if size > 1,
9527    * and if right is not same to result (!!!) -- VR */
9528   if (!pic16_sameRegs(AOP(left),AOP(result))
9529       && (AOP_SIZE(result) > 1)) {
9530
9531     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9532
9533     size = AOP_SIZE(result);
9534     offset=0;
9535     while (size--) {
9536
9537 #if 0
9538       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9539       if (*l == '@' && (IS_AOP_PREG(result))) {
9540
9541           pic16_emitcode("mov","a,%s",l);
9542           pic16_aopPut(AOP(result),"a",offset);
9543       } else
9544 #endif
9545       {
9546         /* we don't know if left is a literal or a register, take care -- VR */
9547         mov2f(AOP(result), AOP(left), offset);
9548       }
9549       offset++;
9550     }
9551   }
9552
9553   size = AOP_SIZE(result);
9554
9555   /* if it is only one byte then */
9556   if (size == 1) {
9557     if(optimized_for_speed) {
9558       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9559       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9560       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9561       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9562       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9563       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9564       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9565       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9566       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9567       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9568       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9569       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9570     } else {
9571
9572       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9573
9574       tlbl = newiTempLabel(NULL);
9575
9576 #if 1
9577       /* this is already done, why change it? */
9578       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9579                 mov2f(AOP(result), AOP(left), 0);
9580       }
9581 #endif
9582
9583       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9584       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9585       pic16_emitpLabel(tlbl->key);
9586       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9587       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9588       emitSKPC;
9589       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9590     }
9591     goto release ;
9592   }
9593     
9594   if (pic16_sameRegs(AOP(left),AOP(result))) {
9595
9596     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9597     
9598     tlbl = newiTempLabel(NULL);
9599     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9600     genMultiAsm(POC_RRCF, result, size,1);
9601     pic16_emitpLabel(tlbl->key);
9602     genMultiAsm(POC_RLCF, result, size,0);
9603     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9604     emitSKPC;
9605     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9606     goto release;
9607   }
9608
9609   //tlbl = newiTempLabel(NULL);
9610   //offset = 0 ;   
9611   //tlbl1 = newiTempLabel(NULL);
9612
9613   //reAdjustPreg(AOP(result));    
9614     
9615   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9616   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9617   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9618   //MOVA(l);
9619   //pic16_emitcode("add","a,acc");         
9620   //pic16_aopPut(AOP(result),"a",offset++);
9621   //while (--size) {
9622   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9623   //  MOVA(l);
9624   //  pic16_emitcode("rlc","a");         
9625   //  pic16_aopPut(AOP(result),"a",offset++);
9626   //}
9627   //reAdjustPreg(AOP(result));
9628
9629   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9630   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9631
9632
9633   tlbl = newiTempLabel(NULL);
9634   tlbl1= newiTempLabel(NULL);
9635
9636   size = AOP_SIZE(result);
9637   offset = 1;
9638
9639   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9640
9641   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9642
9643   /* offset should be 0, 1 or 3 */
9644   
9645   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9646   emitSKPNZ;
9647   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9648
9649   pic16_emitpcode(POC_MOVWF, pctemp);
9650
9651
9652   pic16_emitpLabel(tlbl->key);
9653
9654   emitCLRC;
9655   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9656   while(--size)
9657     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9658
9659   pic16_emitpcode(POC_DECFSZ,  pctemp);
9660   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9661   pic16_emitpLabel(tlbl1->key);
9662
9663   pic16_popReleaseTempReg(pctemp,1);
9664
9665
9666  release:
9667   pic16_freeAsmop (right,NULL,ic,TRUE);
9668   pic16_freeAsmop(left,NULL,ic,TRUE);
9669   pic16_freeAsmop(result,NULL,ic,TRUE);
9670 }
9671 #endif
9672
9673
9674 #if 0
9675 #error old code (left here for reference)
9676 /*-----------------------------------------------------------------*/
9677 /* genLeftShift - generates code for left shifting                 */
9678 /*-----------------------------------------------------------------*/
9679 static void genLeftShift (iCode *ic)
9680 {
9681   operand *left,*right, *result;
9682   int size, offset;
9683   char *l;
9684   symbol *tlbl , *tlbl1;
9685   pCodeOp *pctemp;
9686
9687   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9688
9689   right = IC_RIGHT(ic);
9690   left  = IC_LEFT(ic);
9691   result = IC_RESULT(ic);
9692
9693   pic16_aopOp(right,ic,FALSE);
9694
9695   /* if the shift count is known then do it 
9696      as efficiently as possible */
9697   if (AOP_TYPE(right) == AOP_LIT) {
9698     pic16_genLeftShiftLiteral (left,right,result,ic);
9699     return ;
9700   }
9701
9702   /* shift count is unknown then we have to form 
9703      a loop get the loop count in B : Note: we take
9704      only the lower order byte since shifting
9705      more that 32 bits make no sense anyway, ( the
9706      largest size of an object can be only 32 bits ) */  
9707
9708     
9709   pic16_aopOp(left,ic,FALSE);
9710   pic16_aopOp(result,ic,FALSE);
9711
9712   /* now move the left to the result if they are not the
9713      same */
9714   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9715       AOP_SIZE(result) > 1) {
9716
9717     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9718
9719     size = AOP_SIZE(result);
9720     offset=0;
9721     while (size--) {
9722       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9723       if (*l == '@' && (IS_AOP_PREG(result))) {
9724
9725         pic16_emitcode("mov","a,%s",l);
9726         pic16_aopPut(AOP(result),"a",offset);
9727       } else {
9728
9729         /* we don't know if left is a literal or a register, take care -- VR */
9730         mov2f(AOP(result), AOP(left), offset);
9731       }
9732       offset++;
9733     }
9734   }
9735
9736   size = AOP_SIZE(result);
9737
9738   /* if it is only one byte then */
9739   if (size == 1) {
9740     if(optimized_for_speed) {
9741       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9742       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9743       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9744       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9745       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9746       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9747       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9748       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9749       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9750       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9751       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9752       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9753     } else {
9754
9755       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9756
9757       tlbl = newiTempLabel(NULL);
9758       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9759                 mov2f(AOP(result), AOP(left), 0);
9760                 
9761 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9762 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9763       }
9764
9765       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9766       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9767       pic16_emitpLabel(tlbl->key);
9768       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9769       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9770       emitSKPC;
9771       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9772     }
9773     goto release ;
9774   }
9775     
9776   if (pic16_sameRegs(AOP(left),AOP(result))) {
9777
9778     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9779     
9780     tlbl = newiTempLabel(NULL);
9781     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9782     genMultiAsm(POC_RRCF, result, size,1);
9783     pic16_emitpLabel(tlbl->key);
9784     genMultiAsm(POC_RLCF, result, size,0);
9785     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9786     emitSKPC;
9787     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9788     goto release;
9789   }
9790
9791   //tlbl = newiTempLabel(NULL);
9792   //offset = 0 ;   
9793   //tlbl1 = newiTempLabel(NULL);
9794
9795   //reAdjustPreg(AOP(result));    
9796     
9797   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9798   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9799   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9800   //MOVA(l);
9801   //pic16_emitcode("add","a,acc");         
9802   //pic16_aopPut(AOP(result),"a",offset++);
9803   //while (--size) {
9804   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9805   //  MOVA(l);
9806   //  pic16_emitcode("rlc","a");         
9807   //  pic16_aopPut(AOP(result),"a",offset++);
9808   //}
9809   //reAdjustPreg(AOP(result));
9810
9811   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9812   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9813
9814
9815   tlbl = newiTempLabel(NULL);
9816   tlbl1= newiTempLabel(NULL);
9817
9818   size = AOP_SIZE(result);
9819   offset = 1;
9820
9821   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9822
9823   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9824
9825   /* offset should be 0, 1 or 3 */
9826   
9827   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9828   emitSKPNZ;
9829   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9830
9831   pic16_emitpcode(POC_MOVWF, pctemp);
9832
9833
9834   pic16_emitpLabel(tlbl->key);
9835
9836   emitCLRC;
9837   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9838   while(--size)
9839     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9840
9841   pic16_emitpcode(POC_DECFSZ,  pctemp);
9842   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9843   pic16_emitpLabel(tlbl1->key);
9844
9845   pic16_popReleaseTempReg(pctemp,1);
9846
9847
9848  release:
9849   pic16_freeAsmop (right,NULL,ic,TRUE);
9850   pic16_freeAsmop(left,NULL,ic,TRUE);
9851   pic16_freeAsmop(result,NULL,ic,TRUE);
9852 }
9853 #endif
9854
9855 /*-----------------------------------------------------------------*/
9856 /* genrshOne - right shift a one byte quantity by known count      */
9857 /*-----------------------------------------------------------------*/
9858 static void genrshOne (operand *result, operand *left,
9859                        int shCount, int sign)
9860 {
9861     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9862     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9863 }
9864
9865 /*-----------------------------------------------------------------*/
9866 /* genrshTwo - right shift two bytes by known amount != 0          */
9867 /*-----------------------------------------------------------------*/
9868 static void genrshTwo (operand *result,operand *left,
9869                        int shCount, int sign)
9870 {
9871   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9872   /* if shCount >= 8 */
9873   if (shCount >= 8) {
9874     shCount -= 8 ;
9875     if (shCount)
9876       shiftR1Left2Result(left, MSB16, result, LSB,
9877                          shCount, sign);
9878     else
9879       movLeft2Result(left, MSB16, result, LSB);
9880
9881     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9882
9883     if(sign) {
9884       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9885       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
9886     }
9887   }
9888
9889   /*  1 <= shCount <= 7 */
9890   else
9891     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9892 }
9893
9894 /*-----------------------------------------------------------------*/
9895 /* shiftRLong - shift right one long from left to result           */
9896 /* offl = LSB or MSB16                                             */
9897 /*-----------------------------------------------------------------*/
9898 static void shiftRLong (operand *left, int offl,
9899                         operand *result, int sign)
9900 {
9901     int size = AOP_SIZE(result);
9902     int same = pic16_sameRegs(AOP(left),AOP(result));
9903     int i;
9904     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9905
9906         if (same && (offl == MSB16)) { //shift one byte right
9907                 for(i=MSB16;i<size;i++) {
9908                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9909                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9910                 }
9911         }
9912
9913     if(sign)
9914                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9915         else
9916                 emitCLRC;
9917
9918         if (same) {
9919                 if (offl == LSB)
9920                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9921         } else {
9922         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9923         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9924         }
9925
9926     if(offl == MSB16) {
9927         /* add sign of "a" */
9928         pic16_addSign(result, MSB32, sign);
9929         }
9930
9931         if (same) {
9932         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9933         } else {
9934         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9935         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9936         }
9937         
9938         if (same) {
9939         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9940         } else {
9941         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9942         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9943         }
9944
9945         if (same) {
9946         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9947         } else {
9948         if(offl == LSB){
9949                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9950                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9951         }
9952         }
9953 }
9954
9955 /*-----------------------------------------------------------------*/
9956 /* genrshFour - shift four byte by a known amount != 0             */
9957 /*-----------------------------------------------------------------*/
9958 static void genrshFour (operand *result, operand *left,
9959                         int shCount, int sign)
9960 {
9961   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9962   /* if shifting more that 3 bytes */
9963   if(shCount >= 24 ) {
9964     shCount -= 24;
9965     if(shCount)
9966       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9967     else
9968       movLeft2Result(left, MSB32, result, LSB);
9969
9970     pic16_addSign(result, MSB16, sign);
9971   }
9972   else if(shCount >= 16){
9973     shCount -= 16;
9974     if(shCount)
9975       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9976     else{
9977       movLeft2Result(left, MSB24, result, LSB);
9978       movLeft2Result(left, MSB32, result, MSB16);
9979     }
9980     pic16_addSign(result, MSB24, sign);
9981   }
9982   else if(shCount >= 8){
9983     shCount -= 8;
9984     if(shCount == 1)
9985       shiftRLong(left, MSB16, result, sign);
9986     else if(shCount == 0){
9987       movLeft2Result(left, MSB16, result, LSB);
9988       movLeft2Result(left, MSB24, result, MSB16);
9989       movLeft2Result(left, MSB32, result, MSB24);
9990       pic16_addSign(result, MSB32, sign);
9991     }
9992     else{ //shcount >= 2
9993       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9994       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9995       /* the last shift is signed */
9996       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9997       pic16_addSign(result, MSB32, sign);
9998     }
9999   }
10000   else{   /* 1 <= shCount <= 7 */
10001     if(shCount <= 2){
10002       shiftRLong(left, LSB, result, sign);
10003       if(shCount == 2)
10004         shiftRLong(result, LSB, result, sign);
10005     }
10006     else{
10007       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10008       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10009       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10010     }
10011   }
10012 }
10013
10014 /*-----------------------------------------------------------------*/
10015 /* genRightShiftLiteral - right shifting by known count            */
10016 /*-----------------------------------------------------------------*/
10017 static void genRightShiftLiteral (operand *left,
10018                                   operand *right,
10019                                   operand *result,
10020                                   iCode *ic,
10021                                   int sign)
10022 {    
10023   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10024   int lsize,res_size;
10025
10026   pic16_freeAsmop(right,NULL,ic,TRUE);
10027
10028   pic16_aopOp(left,ic,FALSE);
10029   pic16_aopOp(result,ic,TRUE);
10030
10031   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10032
10033 #if VIEW_SIZE
10034   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10035                  AOP_SIZE(left));
10036 #endif
10037
10038   lsize = pic16_getDataSize(left);
10039   res_size = pic16_getDataSize(result);
10040   /* test the LEFT size !!! */
10041
10042   /* I suppose that the left size >= result size */
10043   if(shCount == 0){
10044     assert (res_size <= lsize);
10045     while (res_size--) {
10046       mov2f (AOP(result), AOP(left), res_size);
10047     } // for
10048   }
10049
10050   else if(shCount >= (lsize * 8)){
10051
10052     if(res_size == 1) {
10053       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10054       if(sign) {
10055         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10056         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10057       }
10058     } else {
10059
10060       if(sign) {
10061         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10062         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10063         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10064         while(res_size--)
10065           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10066
10067       } else {
10068
10069         while(res_size--)
10070           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10071       }
10072     }
10073   } else {
10074
10075     switch (res_size) {
10076     case 1:
10077       genrshOne (result,left,shCount,sign);
10078       break;
10079
10080     case 2:
10081       genrshTwo (result,left,shCount,sign);
10082       break;
10083
10084     case 4:
10085       genrshFour (result,left,shCount,sign);
10086       break;
10087     default :
10088       break;
10089     }
10090
10091   }
10092
10093   pic16_freeAsmop(left,NULL,ic,TRUE);
10094   pic16_freeAsmop(result,NULL,ic,TRUE);
10095 }
10096
10097 #if !(USE_GENERIC_SIGNED_SHIFT)
10098 /*-----------------------------------------------------------------*/
10099 /* genSignedRightShift - right shift of signed number              */
10100 /*-----------------------------------------------------------------*/
10101 static void genSignedRightShift (iCode *ic)
10102 {
10103   operand *right, *left, *result;
10104   int size, offset;
10105   //  char *l;
10106   symbol *tlbl, *tlbl1 ;
10107   pCodeOp *pctemp;
10108
10109   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10110
10111   /* we do it the hard way put the shift count in b
10112      and loop thru preserving the sign */
10113   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10114
10115   right = IC_RIGHT(ic);
10116   left  = IC_LEFT(ic);
10117   result = IC_RESULT(ic);
10118
10119   pic16_aopOp(right,ic,FALSE);  
10120   pic16_aopOp(left,ic,FALSE);
10121   pic16_aopOp(result,ic,FALSE);
10122
10123
10124   if ( AOP_TYPE(right) == AOP_LIT) {
10125     genRightShiftLiteral (left,right,result,ic,1);
10126     return ;
10127   }
10128   /* shift count is unknown then we have to form 
10129      a loop get the loop count in B : Note: we take
10130      only the lower order byte since shifting
10131      more that 32 bits make no sense anyway, ( the
10132      largest size of an object can be only 32 bits ) */  
10133
10134   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10135   //pic16_emitcode("inc","b");
10136   //pic16_freeAsmop (right,NULL,ic,TRUE);
10137   //pic16_aopOp(left,ic,FALSE);
10138   //pic16_aopOp(result,ic,FALSE);
10139
10140   /* now move the left to the result if they are not the
10141      same */
10142   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10143       AOP_SIZE(result) > 1) {
10144
10145     size = AOP_SIZE(result);
10146     offset=0;
10147     while (size--) { 
10148       /*
10149         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10150         if (*l == '@' && IS_AOP_PREG(result)) {
10151
10152         pic16_emitcode("mov","a,%s",l);
10153         pic16_aopPut(AOP(result),"a",offset);
10154         } else
10155         pic16_aopPut(AOP(result),l,offset);
10156       */
10157       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10158       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10159
10160       offset++;
10161     }
10162   }
10163
10164   /* mov the highest order bit to OVR */    
10165   tlbl = newiTempLabel(NULL);
10166   tlbl1= newiTempLabel(NULL);
10167
10168   size = AOP_SIZE(result);
10169   offset = size - 1;
10170
10171   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10172
10173   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10174
10175   /* offset should be 0, 1 or 3 */
10176   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10177   emitSKPNZ;
10178   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10179
10180   pic16_emitpcode(POC_MOVWF, pctemp);
10181
10182
10183   pic16_emitpLabel(tlbl->key);
10184
10185   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10186   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10187
10188   while(--size) {
10189     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10190   }
10191
10192   pic16_emitpcode(POC_DECFSZ,  pctemp);
10193   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10194   pic16_emitpLabel(tlbl1->key);
10195
10196   pic16_popReleaseTempReg(pctemp,1);
10197 #if 0
10198   size = AOP_SIZE(result);
10199   offset = size - 1;
10200   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10201   pic16_emitcode("rlc","a");
10202   pic16_emitcode("mov","ov,c");
10203   /* if it is only one byte then */
10204   if (size == 1) {
10205     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10206     MOVA(l);
10207     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10208     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10209     pic16_emitcode("mov","c,ov");
10210     pic16_emitcode("rrc","a");
10211     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10212     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10213     pic16_aopPut(AOP(result),"a",0);
10214     goto release ;
10215   }
10216
10217   reAdjustPreg(AOP(result));
10218   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10219   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10220   pic16_emitcode("mov","c,ov");
10221   while (size--) {
10222     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10223     MOVA(l);
10224     pic16_emitcode("rrc","a");         
10225     pic16_aopPut(AOP(result),"a",offset--);
10226   }
10227   reAdjustPreg(AOP(result));
10228   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10229   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10230
10231  release:
10232 #endif
10233
10234   pic16_freeAsmop(left,NULL,ic,TRUE);
10235   pic16_freeAsmop(result,NULL,ic,TRUE);
10236   pic16_freeAsmop(right,NULL,ic,TRUE);
10237 }
10238 #endif
10239
10240 #if !(USE_GENERIC_SIGNED_SHIFT)
10241 #warning This implementation of genRightShift() is incomplete!
10242 /*-----------------------------------------------------------------*/
10243 /* genRightShift - generate code for right shifting                */
10244 /*-----------------------------------------------------------------*/
10245 static void genRightShift (iCode *ic)
10246 {
10247     operand *right, *left, *result;
10248     sym_link *letype ;
10249     int size, offset;
10250     char *l;
10251     symbol *tlbl, *tlbl1 ;
10252
10253     /* if signed then we do it the hard way preserve the
10254     sign bit moving it inwards */
10255     letype = getSpec(operandType(IC_LEFT(ic)));
10256     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10257
10258     if (!SPEC_USIGN(letype)) {
10259         genSignedRightShift (ic);
10260         return ;
10261     }
10262
10263     /* signed & unsigned types are treated the same : i.e. the
10264     signed is NOT propagated inwards : quoting from the
10265     ANSI - standard : "for E1 >> E2, is equivalent to division
10266     by 2**E2 if unsigned or if it has a non-negative value,
10267     otherwise the result is implementation defined ", MY definition
10268     is that the sign does not get propagated */
10269
10270     right = IC_RIGHT(ic);
10271     left  = IC_LEFT(ic);
10272     result = IC_RESULT(ic);
10273
10274     pic16_aopOp(right,ic,FALSE);
10275
10276     /* if the shift count is known then do it 
10277     as efficiently as possible */
10278     if (AOP_TYPE(right) == AOP_LIT) {
10279         genRightShiftLiteral (left,right,result,ic, 0);
10280         return ;
10281     }
10282
10283     /* shift count is unknown then we have to form 
10284     a loop get the loop count in B : Note: we take
10285     only the lower order byte since shifting
10286     more that 32 bits make no sense anyway, ( the
10287     largest size of an object can be only 32 bits ) */  
10288
10289     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10290     pic16_emitcode("inc","b");
10291     pic16_aopOp(left,ic,FALSE);
10292     pic16_aopOp(result,ic,FALSE);
10293
10294     /* now move the left to the result if they are not the
10295     same */
10296     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10297         AOP_SIZE(result) > 1) {
10298
10299         size = AOP_SIZE(result);
10300         offset=0;
10301         while (size--) {
10302             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10303             if (*l == '@' && IS_AOP_PREG(result)) {
10304
10305                 pic16_emitcode("mov","a,%s",l);
10306                 pic16_aopPut(AOP(result),"a",offset);
10307             } else
10308                 pic16_aopPut(AOP(result),l,offset);
10309             offset++;
10310         }
10311     }
10312
10313     tlbl = newiTempLabel(NULL);
10314     tlbl1= newiTempLabel(NULL);
10315     size = AOP_SIZE(result);
10316     offset = size - 1;
10317
10318     /* if it is only one byte then */
10319     if (size == 1) {
10320
10321       tlbl = newiTempLabel(NULL);
10322       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10323         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10324         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10325       }
10326
10327       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10328       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10329       pic16_emitpLabel(tlbl->key);
10330       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10331       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10332       emitSKPC;
10333       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10334
10335       goto release ;
10336     }
10337
10338     reAdjustPreg(AOP(result));
10339     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10340     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10341     CLRC;
10342     while (size--) {
10343         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10344         MOVA(l);
10345         pic16_emitcode("rrc","a");         
10346         pic16_aopPut(AOP(result),"a",offset--);
10347     }
10348     reAdjustPreg(AOP(result));
10349
10350     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10351     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10352
10353 release:
10354     pic16_freeAsmop(left,NULL,ic,TRUE);
10355     pic16_freeAsmop (right,NULL,ic,TRUE);
10356     pic16_freeAsmop(result,NULL,ic,TRUE);
10357 }
10358 #endif
10359
10360 #if (USE_GENERIC_SIGNED_SHIFT)
10361 /*-----------------------------------------------------------------*/
10362 /* genGenericShift - generates code for left or right shifting     */
10363 /*-----------------------------------------------------------------*/
10364 static void genGenericShift (iCode *ic, int isShiftLeft) {
10365   operand *left,*right, *result;
10366   int offset;
10367   int sign, signedCount;
10368   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10369   PIC_OPCODE pos_shift, neg_shift;
10370
10371   FENTRY;
10372
10373   right = IC_RIGHT(ic);
10374   left  = IC_LEFT(ic);
10375   result = IC_RESULT(ic);
10376
10377   pic16_aopOp(right,ic,FALSE);
10378   pic16_aopOp(left,ic,FALSE);
10379   pic16_aopOp(result,ic,TRUE);
10380
10381   sign = !SPEC_USIGN(operandType (left));
10382   signedCount = !SPEC_USIGN(operandType (right));
10383
10384   /* if the shift count is known then do it 
10385      as efficiently as possible */
10386   if (AOP_TYPE(right) == AOP_LIT) {
10387     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10388     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10389     // we should modify right->aopu.aop_lit here!
10390     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10391     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10392     if (isShiftLeft)
10393       pic16_genLeftShiftLiteral (left,right,result,ic);
10394     else
10395       genRightShiftLiteral (left,right,result,ic, sign);
10396
10397     goto release;
10398   } // if (right is literal)
10399
10400   /* shift count is unknown then we have to form a loop.
10401    * Note: we take only the lower order byte since shifting
10402    * more than 32 bits make no sense anyway, ( the
10403    * largest size of an object can be only 32 bits )
10404    * Note: we perform arithmetic shifts if the left operand is
10405    * signed and we do an (effective) right shift, i. e. we
10406    * shift in the sign bit from the left. */
10407    
10408   label_complete = newiTempLabel ( NULL );
10409   label_loop_pos = newiTempLabel ( NULL );
10410   label_loop_neg = NULL;
10411   label_negative = NULL;
10412   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10413   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10414
10415   if (signedCount) {
10416     // additional labels needed
10417     label_loop_neg = newiTempLabel ( NULL );
10418     label_negative = newiTempLabel ( NULL );
10419   } // if
10420
10421   // copy source to result -- this will effectively truncate the left operand to the size of result!
10422   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10423   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10424   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10425     mov2f (AOP(result),AOP(left), offset);
10426   } // for
10427
10428   // if result is longer than left, fill with zeros (or sign)
10429   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10430     if (sign && AOP_SIZE(left) > 0) {
10431       // shift signed operand -- fill with sign
10432       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10433       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10434       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10435       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10436         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10437       } // for
10438     } else {
10439       // shift unsigned operand -- fill result with zeros
10440       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10441         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10442       } // for
10443     }
10444   } // if (size mismatch)
10445
10446   pic16_mov2w (AOP(right), 0);
10447   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10448   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10449   
10450 #if 0
10451   // perform a shift by one (shift count is positive)
10452   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10453   // 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])
10454   pic16_emitpLabel (label_loop_pos->key);
10455   emitCLRC;
10456   if (sign && (pos_shift == POC_RRCF)) {
10457     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10458     emitSETC;
10459   } // if
10460   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10461   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10462   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10463 #else
10464   // perform a shift by one (shift count is positive)
10465   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10466   // 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])
10467   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10468   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10469   emitCLRC;
10470   pic16_emitpLabel (label_loop_pos->key);
10471   if (sign && (pos_shift == POC_RRCF)) {
10472     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10473     emitSETC;
10474   } // if
10475   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10476   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10477   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10478   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10479 #endif
10480
10481   if (signedCount) {
10482     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10483
10484     pic16_emitpLabel (label_negative->key);
10485     // perform a shift by -1 (shift count is negative)
10486     // 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)
10487     emitCLRC;
10488     pic16_emitpLabel (label_loop_neg->key);
10489     if (sign && (neg_shift == POC_RRCF)) {
10490       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10491       emitSETC;
10492     } // if
10493     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10494     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10495     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10496     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10497   } // if (signedCount)
10498
10499   pic16_emitpLabel (label_complete->key);
10500
10501 release:
10502   pic16_freeAsmop (right,NULL,ic,TRUE);
10503   pic16_freeAsmop(left,NULL,ic,TRUE);
10504   pic16_freeAsmop(result,NULL,ic,TRUE);
10505 }
10506
10507 static void genLeftShift (iCode *ic) {
10508   genGenericShift (ic, 1);
10509 }
10510
10511 static void genRightShift (iCode *ic) {
10512   genGenericShift (ic, 0);
10513 }
10514 #endif
10515
10516
10517 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10518 void pic16_loadFSR0(operand *op, int lit)
10519 {
10520   if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10521     pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10522   } else {
10523     assert (!OP_SYMBOL(op)->remat);
10524     // set up FSR0 with address of result
10525     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10526     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10527   }
10528 }
10529
10530 /*-----------------------------------------------------------------*/
10531 /* genUnpackBits - generates code for unpacking bits               */
10532 /*-----------------------------------------------------------------*/
10533 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10534 {    
10535   int shCnt ;
10536   int rlen = 0 ;
10537   sym_link *etype, *letype;
10538   int blen=0, bstr=0;
10539   int lbstr;
10540   int offset = 0 ;
10541
10542     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10543     etype = getSpec(operandType(result));
10544     letype = getSpec(operandType(left));
10545     
10546 //    if(IS_BITFIELD(etype)) {
10547       blen = SPEC_BLEN(etype);
10548       bstr = SPEC_BSTR(etype);
10549 //    }
10550
10551     lbstr = SPEC_BSTR( letype );
10552
10553 #if 1
10554     if((blen == 1) && (bstr < 8)) {
10555       /* it is a single bit, so use the appropriate bit instructions */
10556       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10557
10558       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10559       
10560       // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10561       if(OP_SYMBOL(left)->remat && (ptype == POINTER) && (result)) {
10562         /* workaround to reduce the extra lfsr instruction */
10563         pic16_emitpcode(POC_BTFSC,
10564               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10565       } else {
10566         pic16_loadFSR0 (left, 0);
10567         pic16_emitpcode(POC_BTFSC,
10568               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10569       }
10570         
10571       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10572
10573       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10574       return;
10575     }
10576
10577 #endif
10578
10579         /* the following call to pic16_loadFSR0 is temporary until
10580          * optimization to handle single bit assignments is added
10581          * to the function. Until then use the old safe way! -- VR */
10582
10583     if (OP_SYMBOL(left)->remat) {
10584         // access symbol directly
10585         pic16_mov2w (AOP(left), 0);
10586     } else {
10587         pic16_loadFSR0( left, 0 );
10588  
10589         /* read the first byte  */
10590         switch (ptype) {
10591                 case POINTER:
10592                 case IPOINTER:
10593                 case PPOINTER:
10594                 case FPOINTER:
10595                 case GPOINTER:
10596                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10597                         break;
10598                 case CPOINTER:
10599                         pic16_emitcode("clr","a");
10600                         pic16_emitcode("movc","a","@a+dptr");
10601                         assert (0);
10602                         break;
10603         }
10604     }
10605
10606         /* if we have bitdisplacement then it fits   */
10607         /* into this byte completely or if length is */
10608         /* less than a byte                          */
10609         if ((shCnt = SPEC_BSTR(etype)) || 
10610                 (SPEC_BLEN(etype) <= 8))  {
10611
10612                 /* shift right acc */
10613                 AccRsh(shCnt, 0);
10614
10615                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10616                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10617
10618 /* VR -- normally I would use the following, but since we use the hack,
10619  * to avoid the masking from AccRsh, why not mask it right now? */
10620
10621 /*
10622                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10623 */
10624
10625                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10626           return ;
10627         }
10628
10629
10630
10631         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10632         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10633         exit(-1);
10634
10635     /* bit field did not fit in a byte  */
10636     rlen = SPEC_BLEN(etype) - 8;
10637     pic16_aopPut(AOP(result),"a",offset++);
10638
10639     while (1)  {
10640
10641         switch (ptype) {
10642         case POINTER:
10643         case IPOINTER:
10644             pic16_emitcode("inc","%s",rname);
10645             pic16_emitcode("mov","a,@%s",rname);
10646             break;
10647             
10648         case PPOINTER:
10649             pic16_emitcode("inc","%s",rname);
10650             pic16_emitcode("movx","a,@%s",rname);
10651             break;
10652
10653         case FPOINTER:
10654             pic16_emitcode("inc","dptr");
10655             pic16_emitcode("movx","a,@dptr");
10656             break;
10657             
10658         case CPOINTER:
10659             pic16_emitcode("clr","a");
10660             pic16_emitcode("inc","dptr");
10661             pic16_emitcode("movc","a","@a+dptr");
10662             break;
10663             
10664         case GPOINTER:
10665             pic16_emitcode("inc","dptr");
10666             pic16_emitcode("lcall","__gptrget");
10667             break;
10668         }
10669
10670         rlen -= 8;            
10671         /* if we are done */
10672         if ( rlen <= 0 )
10673             break ;
10674         
10675         pic16_aopPut(AOP(result),"a",offset++);
10676                               
10677     }
10678     
10679     if (rlen) {
10680         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10681         pic16_aopPut(AOP(result),"a",offset);          
10682     }
10683     
10684     return ;
10685 }
10686
10687
10688 static void genDataPointerGet(operand *left,
10689                               operand *result,
10690                               iCode *ic)
10691 {
10692   int size, offset = 0, leoffset=0 ;
10693
10694         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10695         pic16_aopOp(result, ic, TRUE);
10696
10697         FENTRY;
10698
10699         size = AOP_SIZE(result);
10700 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10701
10702
10703 #if 0
10704         /* The following tests may save a redudant movff instruction when
10705          * accessing unions */
10706          
10707         /* if they are the same */
10708         if (operandsEqu (left, result)) {
10709                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10710                 goto release;
10711         }
10712 #endif
10713
10714 #if 0
10715         /* if they are the same registers */
10716         if (pic16_sameRegs(AOP(left),AOP(result))) {
10717                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10718                 goto release;
10719         }
10720 #endif
10721
10722 #if 1
10723         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10724                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10725                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10726                 goto release;
10727         }
10728 #endif
10729
10730
10731 #if 0
10732         if ( AOP_TYPE(left) == AOP_PCODE) {
10733                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
10734                                 AOP(left)->aopu.pcop->name,
10735                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
10736                                 PCOR(AOP(left)->aopu.pcop)->instance:
10737                                 PCOI(AOP(left)->aopu.pcop)->offset);
10738         }
10739 #endif
10740
10741         if(AOP(left)->aopu.pcop->type == PO_DIR)
10742                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10743
10744         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10745
10746         while (size--) {
10747                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10748                 
10749 //              pic16_DumpOp("(result)",result);
10750                 if(is_LitAOp(AOP(result))) {
10751                         pic16_mov2w(AOP(left), offset); // patch 8
10752                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10753                 } else {
10754                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10755                                 pic16_popGet(AOP(left), offset), //patch 8
10756                                 pic16_popGet(AOP(result), offset)));
10757                 }
10758
10759                 offset++;
10760                 leoffset++;
10761         }
10762
10763 release:
10764     pic16_freeAsmop(result,NULL,ic,TRUE);
10765 }
10766
10767
10768
10769 /*-----------------------------------------------------------------*/
10770 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10771 /*-----------------------------------------------------------------*/
10772 static void genNearPointerGet (operand *left, 
10773                                operand *result, 
10774                                iCode *ic)
10775 {
10776 //  asmop *aop = NULL;
10777   //regs *preg = NULL ;
10778   sym_link *rtype, *retype;
10779   sym_link *ltype = operandType(left);    
10780
10781     FENTRY;
10782     
10783     rtype = operandType(result);
10784     retype= getSpec(rtype);
10785     
10786     pic16_aopOp(left,ic,FALSE);
10787
10788 //    pic16_DumpOp("(left)",left);
10789 //    pic16_DumpOp("(result)",result);
10790
10791     /* if left is rematerialisable and
10792      * result is not bit variable type and
10793      * the left is pointer to data space i.e
10794      * lower 128 bytes of space */
10795     
10796     if (AOP_TYPE(left) == AOP_PCODE
10797       && !IS_BITFIELD(retype)
10798       && DCL_TYPE(ltype) == POINTER) {
10799
10800         genDataPointerGet (left,result,ic);
10801         pic16_freeAsmop(left, NULL, ic, TRUE);
10802         return ;
10803     }
10804     
10805     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10806     pic16_aopOp (result,ic,TRUE);
10807     
10808     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10809
10810 #if 1
10811     if(IS_BITFIELD( retype )
10812       && (SPEC_BLEN(operandType(result))==1)
10813     ) {
10814       iCode *nextic;
10815       pCodeOp *jop;
10816       int bitstrt, bytestrt;
10817
10818         /* if this is bitfield of size 1, see if we are checking the value
10819          * of a single bit in an if-statement,
10820          * if yes, then don't generate usual code, but execute the
10821          * genIfx directly -- VR */
10822
10823         nextic = ic->next;
10824
10825         /* CHECK: if next iCode is IFX
10826          * and current result operand is nextic's conditional operand
10827          * and current result operand live ranges ends at nextic's key number
10828          */
10829         if((nextic->op == IFX)
10830           && (result == IC_COND(nextic))
10831           && (OP_LIVETO(result) == nextic->seq)
10832           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10833           ) {
10834             /* everything is ok then */
10835             /* find a way to optimize the genIfx iCode */
10836
10837             bytestrt = SPEC_BSTR(operandType(result))/8;
10838             bitstrt = SPEC_BSTR(operandType(result))%8;
10839             
10840             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10841
10842             genIfxpCOpJump(nextic, jop);
10843             
10844             pic16_freeAsmop(left, NULL, ic, TRUE);
10845             pic16_freeAsmop(result, NULL, ic, TRUE);
10846             return;
10847         }
10848     }
10849 #endif
10850
10851
10852     /* if the value is already in a pointer register
10853      * then don't need anything more */
10854     if (1 || !AOP_INPREG(AOP(left))) {  // AOP_INPREG(AOP(left)) is not always correct...
10855       /* otherwise get a free pointer register */
10856       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10857                 
10858       ;
10859     }
10860
10861     /* if bitfield then unpack the bits */
10862     if (IS_BITFIELD(retype)) 
10863       genUnpackBits (result, left, NULL, POINTER);
10864     else {
10865       /* we have can just get the values */
10866       int size = AOP_SIZE(result);
10867       int offset = 0;   
10868         
10869       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10870
10871       pic16_loadFSR0( left, 0 );
10872
10873       while(size--) {
10874         if(size) {
10875           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10876                 pic16_popGet(AOP(result), offset++)));
10877         } else {
10878           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10879                 pic16_popGet(AOP(result), offset++)));
10880         }
10881       }
10882     }
10883
10884 #if 0
10885     /* now some housekeeping stuff */
10886     if (aop) {
10887       /* we had to allocate for this iCode */
10888       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10889       pic16_freeAsmop(NULL,aop,ic,TRUE);
10890     } else { 
10891       /* we did not allocate which means left
10892        * already in a pointer register, then
10893        * if size > 0 && this could be used again
10894        * we have to point it back to where it 
10895        * belongs */
10896       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10897       if (AOP_SIZE(result) > 1
10898         && !OP_SYMBOL(left)->remat
10899         && ( OP_SYMBOL(left)->liveTo > ic->seq
10900             || ic->depth )) {
10901 //        int size = AOP_SIZE(result) - 1;
10902 //        while (size--)
10903 //          pic16_emitcode("dec","%s",rname);
10904         }
10905     }
10906 #endif
10907
10908     /* done */
10909     pic16_freeAsmop(left,NULL,ic,TRUE);
10910     pic16_freeAsmop(result,NULL,ic,TRUE);
10911 }
10912
10913 /*-----------------------------------------------------------------*/
10914 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10915 /*-----------------------------------------------------------------*/
10916 static void genPagedPointerGet (operand *left, 
10917                                operand *result, 
10918                                iCode *ic)
10919 {
10920     asmop *aop = NULL;
10921     regs *preg = NULL ;
10922     char *rname ;
10923     sym_link *rtype, *retype;    
10924
10925     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10926
10927     rtype = operandType(result);
10928     retype= getSpec(rtype);
10929     
10930     pic16_aopOp(left,ic,FALSE);
10931
10932   /* if the value is already in a pointer register
10933        then don't need anything more */
10934     if (!AOP_INPREG(AOP(left))) {
10935         /* otherwise get a free pointer register */
10936         aop = newAsmop(0);
10937         preg = getFreePtr(ic,&aop,FALSE);
10938         pic16_emitcode("mov","%s,%s",
10939                 preg->name,
10940                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10941         rname = preg->name ;
10942     } else
10943         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10944     
10945     pic16_freeAsmop(left,NULL,ic,TRUE);
10946     pic16_aopOp (result,ic,TRUE);
10947
10948     /* if bitfield then unpack the bits */
10949     if (IS_BITFIELD(retype)) 
10950         genUnpackBits (result,left,rname,PPOINTER);
10951     else {
10952         /* we have can just get the values */
10953         int size = AOP_SIZE(result);
10954         int offset = 0 ;        
10955         
10956         while (size--) {
10957             
10958             pic16_emitcode("movx","a,@%s",rname);
10959             pic16_aopPut(AOP(result),"a",offset);
10960             
10961             offset++ ;
10962             
10963             if (size)
10964                 pic16_emitcode("inc","%s",rname);
10965         }
10966     }
10967
10968     /* now some housekeeping stuff */
10969     if (aop) {
10970         /* we had to allocate for this iCode */
10971         pic16_freeAsmop(NULL,aop,ic,TRUE);
10972     } else { 
10973         /* we did not allocate which means left
10974            already in a pointer register, then
10975            if size > 0 && this could be used again
10976            we have to point it back to where it 
10977            belongs */
10978         if (AOP_SIZE(result) > 1 &&
10979             !OP_SYMBOL(left)->remat &&
10980             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10981               ic->depth )) {
10982             int size = AOP_SIZE(result) - 1;
10983             while (size--)
10984                 pic16_emitcode("dec","%s",rname);
10985         }
10986     }
10987
10988     /* done */
10989     pic16_freeAsmop(result,NULL,ic,TRUE);
10990     
10991         
10992 }
10993
10994 /*-----------------------------------------------------------------*/
10995 /* genFarPointerGet - gget value from far space                    */
10996 /*-----------------------------------------------------------------*/
10997 static void genFarPointerGet (operand *left,
10998                               operand *result, iCode *ic)
10999 {
11000     int size, offset ;
11001     sym_link *retype = getSpec(operandType(result));
11002
11003     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11004
11005     pic16_aopOp(left,ic,FALSE);
11006
11007     /* if the operand is already in dptr 
11008     then we do nothing else we move the value to dptr */
11009     if (AOP_TYPE(left) != AOP_STR) {
11010         /* if this is remateriazable */
11011         if (AOP_TYPE(left) == AOP_IMMD)
11012             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11013         else { /* we need to get it byte by byte */
11014             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11015             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11016             if (options.model == MODEL_FLAT24)
11017             {
11018                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11019             }
11020         }
11021     }
11022     /* so dptr know contains the address */
11023     pic16_freeAsmop(left,NULL,ic,TRUE);
11024     pic16_aopOp(result,ic,TRUE);
11025
11026     /* if bit then unpack */
11027     if (IS_BITFIELD(retype)) 
11028         genUnpackBits(result,left,"dptr",FPOINTER);
11029     else {
11030         size = AOP_SIZE(result);
11031         offset = 0 ;
11032
11033         while (size--) {
11034             pic16_emitcode("movx","a,@dptr");
11035             pic16_aopPut(AOP(result),"a",offset++);
11036             if (size)
11037                 pic16_emitcode("inc","dptr");
11038         }
11039     }
11040
11041     pic16_freeAsmop(result,NULL,ic,TRUE);
11042 }
11043
11044 #if 0
11045 /*-----------------------------------------------------------------*/
11046 /* genCodePointerGet - get value from code space                  */
11047 /*-----------------------------------------------------------------*/
11048 static void genCodePointerGet (operand *left,
11049                                 operand *result, iCode *ic)
11050 {
11051     int size, offset ;
11052     sym_link *retype = getSpec(operandType(result));
11053
11054     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11055
11056     pic16_aopOp(left,ic,FALSE);
11057
11058     /* if the operand is already in dptr 
11059     then we do nothing else we move the value to dptr */
11060     if (AOP_TYPE(left) != AOP_STR) {
11061         /* if this is remateriazable */
11062         if (AOP_TYPE(left) == AOP_IMMD)
11063             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11064         else { /* we need to get it byte by byte */
11065             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11066             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11067             if (options.model == MODEL_FLAT24)
11068             {
11069                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11070             }
11071         }
11072     }
11073     /* so dptr know contains the address */
11074     pic16_freeAsmop(left,NULL,ic,TRUE);
11075     pic16_aopOp(result,ic,FALSE);
11076
11077     /* if bit then unpack */
11078     if (IS_BITFIELD(retype)) 
11079         genUnpackBits(result,left,"dptr",CPOINTER);
11080     else {
11081         size = AOP_SIZE(result);
11082         offset = 0 ;
11083
11084         while (size--) {
11085             pic16_emitcode("clr","a");
11086             pic16_emitcode("movc","a,@a+dptr");
11087             pic16_aopPut(AOP(result),"a",offset++);
11088             if (size)
11089                 pic16_emitcode("inc","dptr");
11090         }
11091     }
11092
11093     pic16_freeAsmop(result,NULL,ic,TRUE);
11094 }
11095 #endif
11096
11097 #if 0
11098 /*-----------------------------------------------------------------*/
11099 /* genGenPointerGet - gget value from generic pointer space        */
11100 /*-----------------------------------------------------------------*/
11101 static void genGenPointerGet (operand *left,
11102                               operand *result, iCode *ic)
11103 {
11104   int size, offset, lit;
11105   sym_link *retype = getSpec(operandType(result));
11106
11107         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11108         pic16_aopOp(left,ic,FALSE);
11109         pic16_aopOp(result,ic,FALSE);
11110         size = AOP_SIZE(result);
11111
11112         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11113
11114         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11115
11116                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11117                 // load FSR0 from immediate
11118                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11119
11120 //              pic16_loadFSR0( left );
11121
11122                 offset = 0;
11123                 while(size--) {
11124                         if(size) {
11125                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11126                         } else {
11127                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11128                         }
11129                         offset++;
11130                 }
11131                 goto release;
11132
11133         }
11134         else { /* we need to get it byte by byte */
11135                 // set up FSR0 with address from left
11136                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11137                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11138                 
11139                 offset = 0 ;
11140
11141                 while(size--) {
11142                         if(size) {
11143                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11144                         } else {
11145                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11146                         }
11147                         offset++;
11148                 }
11149                 goto release;
11150         }
11151
11152   /* if bit then unpack */
11153         if (IS_BITFIELD(retype)) 
11154                 genUnpackBits(result,left,"BAD",GPOINTER);
11155
11156         release:
11157         pic16_freeAsmop(left,NULL,ic,TRUE);
11158         pic16_freeAsmop(result,NULL,ic,TRUE);
11159
11160 }
11161 #endif
11162
11163
11164 /*-----------------------------------------------------------------*/
11165 /* genGenPointerGet - gget value from generic pointer space        */
11166 /*-----------------------------------------------------------------*/
11167 static void genGenPointerGet (operand *left,
11168                               operand *result, iCode *ic)
11169 {
11170   int size, offset, lit;
11171   sym_link *retype = getSpec(operandType(result));
11172
11173     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11174     pic16_aopOp(left,ic,FALSE);
11175     pic16_aopOp(result,ic,TRUE);
11176     size = AOP_SIZE(result);
11177
11178     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11179
11180     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11181
11182       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11183       // load FSR0 from immediate
11184       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11185
11186       werror(W_POSSBUG2, __FILE__, __LINE__);
11187
11188       offset = 0;
11189       while(size--) {
11190         if(size) {
11191           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11192         } else {
11193           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11194         }
11195         offset++;
11196       }
11197
11198       goto release;
11199
11200     } else { /* we need to get it byte by byte */
11201
11202       /* set up WREG:PRODL:FSR0L with address from left */
11203       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11204       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11205       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11206       
11207       pic16_callGenericPointerRW(0, size);
11208       
11209       assignResultValue(result, 1);
11210       
11211       goto release;
11212     }
11213
11214   /* if bit then unpack */
11215     if (IS_BITFIELD(retype)) 
11216       genUnpackBits(result,left,"BAD",GPOINTER);
11217
11218 release:
11219   pic16_freeAsmop(left,NULL,ic,TRUE);
11220   pic16_freeAsmop(result,NULL,ic,TRUE);
11221 }
11222
11223 /*-----------------------------------------------------------------*/
11224 /* genConstPointerGet - get value from const generic pointer space */
11225 /*-----------------------------------------------------------------*/
11226 static void genConstPointerGet (operand *left,
11227                                 operand *result, iCode *ic)
11228 {
11229   //sym_link *retype = getSpec(operandType(result));
11230   // symbol *albl = newiTempLabel(NULL);        // patch 15
11231   // symbol *blbl = newiTempLabel(NULL);        //
11232   // PIC_OPCODE poc;                            // patch 15
11233   int size;
11234   int offset = 0;
11235
11236   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11237   pic16_aopOp(left,ic,FALSE);
11238   pic16_aopOp(result,ic,TRUE);
11239   size = AOP_SIZE(result);
11240
11241   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11242
11243   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11244
11245   // set up table pointer
11246   if( (AOP_TYPE(left) == AOP_PCODE) 
11247       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11248           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11249     {
11250       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11251       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11252       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11253       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11254       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11255       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11256   } else {
11257     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11258     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11259     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11260   }
11261
11262   while(size--) {
11263     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11264     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11265     offset++;
11266   }
11267     
11268   pic16_freeAsmop(left,NULL,ic,TRUE);
11269   pic16_freeAsmop(result,NULL,ic,TRUE);
11270 }
11271
11272
11273 /*-----------------------------------------------------------------*/
11274 /* genPointerGet - generate code for pointer get                   */
11275 /*-----------------------------------------------------------------*/
11276 static void genPointerGet (iCode *ic)
11277 {
11278   operand *left, *result ;
11279   sym_link *type, *etype;
11280   int p_type;
11281
11282     FENTRY;
11283     
11284     left = IC_LEFT(ic);
11285     result = IC_RESULT(ic) ;
11286
11287     /* depending on the type of pointer we need to
11288     move it to the correct pointer register */
11289     type = operandType(left);
11290     etype = getSpec(type);
11291
11292 #if 0
11293     if (IS_PTR_CONST(type))
11294 #else
11295     if (IS_CODEPTR(type))
11296 #endif
11297       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11298
11299     /* if left is of type of pointer then it is simple */
11300     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11301       p_type = DCL_TYPE(type);
11302     else {
11303       /* we have to go by the storage class */
11304       p_type = PTR_TYPE(SPEC_OCLS(etype));
11305
11306       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11307
11308       if (SPEC_OCLS(etype)->codesp ) {
11309         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11310         //p_type = CPOINTER ;   
11311       } else
11312       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11313         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11314         /*p_type = FPOINTER ;*/ 
11315       } else
11316       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11317         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11318         /* p_type = PPOINTER; */
11319       } else
11320       if (SPEC_OCLS(etype) == idata ) {
11321         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11322         /* p_type = IPOINTER; */
11323       } else {
11324         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11325         /* p_type = POINTER ; */
11326       }
11327     }
11328
11329     /* now that we have the pointer type we assign
11330     the pointer values */
11331     switch (p_type) {
11332       case POINTER:     
11333       case IPOINTER:
11334         genNearPointerGet (left,result,ic);
11335         break;
11336
11337       case PPOINTER:
11338         genPagedPointerGet(left,result,ic);
11339         break;
11340
11341       case FPOINTER:
11342         genFarPointerGet (left,result,ic);
11343         break;
11344
11345       case CPOINTER:
11346         genConstPointerGet (left,result,ic);
11347         //pic16_emitcodePointerGet (left,result,ic);
11348         break;
11349
11350       case GPOINTER:
11351 #if 0
11352       if (IS_PTR_CONST(type))
11353         genConstPointerGet (left,result,ic);
11354       else
11355 #endif
11356         genGenPointerGet (left,result,ic);
11357       break;
11358
11359     default:
11360       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11361               "genPointerGet: illegal pointer type");
11362     
11363     }
11364 }
11365
11366 /*-----------------------------------------------------------------*/
11367 /* genPackBits - generates code for packed bit storage             */
11368 /*-----------------------------------------------------------------*/
11369 static void genPackBits (sym_link    *etype , operand *result,
11370                          operand *right ,
11371                          char *rname, int p_type)
11372 {
11373   int shCnt = 0 ;
11374   int offset = 0  ;
11375   int rLen = 0 ;
11376   int blen, bstr ;   
11377   sym_link *retype;
11378
11379         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11380         blen = SPEC_BLEN(etype);
11381         bstr = SPEC_BSTR(etype);
11382
11383         retype = getSpec(operandType(right));
11384
11385         if(AOP_TYPE(right) == AOP_LIT) {
11386                 if((blen == 1) && (bstr < 8)) {
11387                   unsigned long lit;
11388                         /* it is a single bit, so use the appropriate bit instructions */
11389
11390                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11391
11392                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11393 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11394                         if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11395                                 /* workaround to reduce the extra lfsr instruction */
11396                                 if(lit) {
11397                                         pic16_emitpcode(POC_BSF,
11398                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11399                                 } else {
11400                                         pic16_emitpcode(POC_BCF,
11401                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11402                                 }
11403                         } else {
11404                                 pic16_loadFSR0(result, 0);
11405                                 if(lit) {
11406                                         pic16_emitpcode(POC_BSF,
11407                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11408                                 } else {
11409                                         pic16_emitpcode(POC_BCF,
11410                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11411                                 }
11412                         }
11413         
11414                   return;
11415                 }
11416                 /* move literal to W */
11417                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11418                 offset++;
11419         } else
11420         if(IS_BITFIELD(retype) 
11421           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11422           && (blen == 1)) {
11423           int rblen, rbstr;
11424
11425             rblen = SPEC_BLEN( retype );
11426             rbstr = SPEC_BSTR( retype );
11427             
11428
11429             if(IS_BITFIELD(etype)) {
11430               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11431               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11432             } else {
11433               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11434             }
11435             
11436             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11437             
11438             if(IS_BITFIELD(etype)) {
11439               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11440             } else {
11441               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11442             }
11443
11444             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11445             
11446             return;
11447         } else {
11448           /* move right to W */
11449           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11450         }
11451
11452         /* if the bit length is less than or   */
11453         /* it exactly fits a byte then         */
11454         if((shCnt=SPEC_BSTR(etype))
11455                 || SPEC_BLEN(etype) <= 8 )  {
11456                 int fsr0_setup = 0;
11457
11458                 if (blen != 8 || bstr != 0) {
11459                   // we need to combine the value with the old value
11460                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11461
11462           DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11463                 SPEC_BSTR(etype), SPEC_BLEN(etype));
11464                 
11465                   /* shift left acc */
11466                   AccLsh(shCnt);
11467
11468                   /* using PRODH as a temporary register here */
11469                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11470
11471                  if (OP_SYMBOL(result)->remat) {
11472                    // access symbol directly
11473                    pic16_mov2w (AOP(result), 0);
11474                  } else {
11475                   /* get old value */
11476                   switch (p_type) {
11477                         case FPOINTER:
11478                         case POINTER:
11479                                 pic16_loadFSR0( result, 0 );
11480                                 fsr0_setup = 1;
11481                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11482 //                              pic16_emitcode ("mov","b,a");
11483 //                              pic16_emitcode("mov","a,@%s",rname);
11484                                 break;
11485
11486                         case GPOINTER:
11487                                 if (AOP(result)->aopu.aop_reg[2]) {
11488                                   // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
11489                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11490                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11491                                   pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11492
11493                                   pic16_callGenericPointerRW(0, 1);
11494                                 } else {
11495                                   // data pointer (just 2 byte given)
11496                                   pic16_loadFSR0( result, 0 );
11497                                   fsr0_setup = 1;
11498                                   pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11499                                 }
11500                                 
11501                                 // warnings will be emitted below
11502                                 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER...");
11503                                 //werror(W_POSSBUG2, __FILE__, __LINE__);
11504                                 break;
11505
11506                         default:
11507                                 assert (0 && "invalid pointer type specified");
11508                                 break;
11509                   }
11510                  }
11511 #if 1
11512                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11513                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11514                                         (unsigned char)(0xff >> (8-bstr))) ));
11515                   pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11516                 } // if (blen != 8 || bstr != 0)
11517
11518                 /* write new value back */
11519                if (OP_SYMBOL(result)->remat) {
11520                 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11521                } else {
11522                 switch (p_type) {
11523                         case FPOINTER:
11524                         case POINTER:
11525                                 if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11526                                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11527                                 break;
11528
11529                         case GPOINTER:
11530                                 if (AOP(result)->aopu.aop_reg[2]) {
11531                                   // prepare call to __gptrset1, this is actually genGenPointerSet(WREG, result, ?ic?)
11532                                   pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec/*pic16_pc_postdec1*/));
11533                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11534                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11535                                   pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11536                                   
11537                                   pic16_callGenericPointerRW(1, 1);
11538                                 } else {
11539                                   // data pointer (just 2 byte given)
11540                                   if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11541                                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11542                                 }
11543                                 
11544                                 // this should work in all cases (as soon as gptrget/gptrput work on EEPROM and PROGRAM MEMORY)
11545                                 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER access");
11546                                 werror(W_POSSBUG2, __FILE__, __LINE__);
11547                                 break;
11548
11549                         default:
11550                                 assert (0 && "invalid pointer type specified");
11551                                 break;
11552                 }
11553                }
11554 #endif
11555
11556           return;
11557         }
11558
11559
11560 #if 0
11561         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11562         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11563         exit(-1);
11564 #endif
11565
11566
11567     pic16_loadFSR0(result, 0);                  // load FSR0 with address of result
11568     rLen = SPEC_BLEN(etype)-8;
11569     
11570     /* now generate for lengths greater than one byte */
11571     while (1) {
11572         rLen -= 8 ;
11573         if (rLen <= 0 ) {
11574           mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11575           break ;
11576         }
11577
11578         switch (p_type) {
11579             case POINTER:
11580                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11581                 break;
11582
11583 /*
11584             case FPOINTER:
11585                 MOVA(l);
11586                 pic16_emitcode("movx","@dptr,a");
11587                 break;
11588
11589             case GPOINTER:
11590                 MOVA(l);
11591                 DEBUGpic16_emitcode(";lcall","__gptrput");
11592                 break;  
11593 */
11594           default:
11595             assert(0);
11596         }   
11597
11598
11599         pic16_mov2w(AOP(right), offset++);
11600     }
11601
11602     /* last last was not complete */
11603     if (rLen)   {
11604         /* save the byte & read byte */
11605         switch (p_type) {
11606             case POINTER:
11607 //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11608                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11609                 break;
11610
11611 /*
11612             case FPOINTER:
11613                 pic16_emitcode ("mov","b,a");
11614                 pic16_emitcode("movx","a,@dptr");
11615                 break;
11616
11617             case GPOINTER:
11618                 pic16_emitcode ("push","b");
11619                 pic16_emitcode ("push","acc");
11620                 pic16_emitcode ("lcall","__gptrget");
11621                 pic16_emitcode ("pop","b");
11622                 break;
11623 */
11624             default:
11625               assert(0);
11626         }
11627         DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11628         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11629         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11630 //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11631 //        pic16_emitcode ("orl","a,b");
11632     }
11633
11634 //    if (p_type == GPOINTER)
11635 //        pic16_emitcode("pop","b");
11636
11637     switch (p_type) {
11638
11639       case POINTER:
11640         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11641 //      pic16_emitcode("mov","@%s,a",rname);
11642         break;
11643 /*
11644       case FPOINTER:
11645         pic16_emitcode("movx","@dptr,a");
11646         break;
11647         
11648       case GPOINTER:
11649         DEBUGpic16_emitcode(";lcall","__gptrput");
11650         break;                  
11651 */
11652       default:
11653         assert(0);
11654     }
11655     
11656 //    pic16_freeAsmop(right, NULL, ic, TRUE);
11657 }
11658 /*-----------------------------------------------------------------*/
11659 /* genDataPointerSet - remat pointer to data space                 */
11660 /*-----------------------------------------------------------------*/
11661 static void genDataPointerSet(operand *right,
11662                               operand *result,
11663                               iCode *ic)
11664 {
11665     int size, offset = 0, resoffset=0 ;
11666
11667     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11668     pic16_aopOp(right,ic,FALSE);
11669
11670     size = AOP_SIZE(right);
11671
11672 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11673
11674 #if 0
11675     if ( AOP_TYPE(result) == AOP_PCODE) {
11676       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11677               AOP(result)->aopu.pcop->name,
11678                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11679               PCOR(AOP(result)->aopu.pcop)->instance:
11680               PCOI(AOP(result)->aopu.pcop)->offset);
11681     }
11682 #endif
11683
11684         if(AOP(result)->aopu.pcop->type == PO_DIR)
11685                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11686
11687         while (size--) {
11688                 if (AOP_TYPE(right) == AOP_LIT) {
11689                   unsigned int lit;
11690
11691                     if(!IS_FLOAT(operandType( right )))
11692                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11693                     else {
11694                       union {
11695                         unsigned long lit_int;
11696                         float lit_float;
11697                       } info;
11698         
11699                         /* take care if literal is a float */
11700                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11701                         lit = info.lit_int;
11702                     }
11703
11704                     lit = lit >> (8*offset);
11705                     if(lit&0xff) {
11706                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11707                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11708                     } else {
11709                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11710                     }
11711                 } else {
11712                   pic16_mov2w(AOP(right), offset);
11713                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11714                 }
11715                 offset++;
11716                 resoffset++;
11717         }
11718
11719     pic16_freeAsmop(right,NULL,ic,TRUE);
11720 }
11721
11722
11723
11724 /*-----------------------------------------------------------------*/
11725 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11726 /*-----------------------------------------------------------------*/
11727 static void genNearPointerSet (operand *right,
11728                                operand *result, 
11729                                iCode *ic)
11730 {
11731   asmop *aop = NULL;
11732   sym_link *retype;
11733   sym_link *ptype = operandType(result);
11734   sym_link *resetype;
11735     
11736         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11737         retype= getSpec(operandType(right));
11738         resetype = getSpec(operandType(result));
11739   
11740         pic16_aopOp(result,ic,FALSE);
11741     
11742         /* if the result is rematerializable &
11743          * in data space & not a bit variable */
11744         
11745         /* and result is not a bit variable */
11746         if (AOP_TYPE(result) == AOP_PCODE
11747 //              && AOP_TYPE(result) == AOP_IMMD
11748                 && DCL_TYPE(ptype) == POINTER
11749                 && !IS_BITFIELD(retype)
11750                 && !IS_BITFIELD(resetype)) {
11751
11752                 genDataPointerSet (right,result,ic);
11753                 pic16_freeAsmop(result,NULL,ic,TRUE);
11754           return;
11755         }
11756
11757         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11758         pic16_aopOp(right,ic,FALSE);
11759         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11760
11761         /* if the value is already in a pointer register
11762          * then don't need anything more */
11763         if (1 || !AOP_INPREG(AOP(result))) {  // AOP_INPREG(AOP(result)) is not always correct...
11764           /* otherwise get a free pointer register */
11765           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11766
11767           ;
11768         }
11769
11770         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11771
11772         /* if bitfield then unpack the bits */
11773         if (IS_BITFIELD(resetype)) {
11774                 genPackBits (resetype, result, right, NULL, POINTER);
11775         } else {
11776                 /* we have can just get the values */
11777           int size = AOP_SIZE(right);
11778           int offset = 0 ;    
11779
11780             pic16_loadFSR0(result, 0);
11781             
11782                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11783                 while (size--) {
11784                                 if (AOP_TYPE(right) == AOP_LIT) {
11785                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11786                                         if (size) {
11787                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11788                                         } else {
11789                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11790                                         }
11791                                 } else { // no literal
11792                                         if(size) {
11793                                                 pic16_emitpcode(POC_MOVFF,
11794                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11795                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11796                                         } else {
11797                                                 pic16_emitpcode(POC_MOVFF,
11798                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11799                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11800                                         }
11801                                 }
11802                         offset++;
11803                 }
11804         }
11805
11806         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11807         /* now some housekeeping stuff */
11808         if (aop) {
11809           /* we had to allocate for this iCode */
11810           pic16_freeAsmop(NULL,aop,ic,TRUE);
11811         } else { 
11812           /* we did not allocate which means left
11813            * already in a pointer register, then
11814            * if size > 0 && this could be used again
11815            * we have to point it back to where it 
11816            * belongs */
11817           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11818           if (AOP_SIZE(right) > 1
11819             && !OP_SYMBOL(result)->remat
11820             && ( OP_SYMBOL(result)->liveTo > ic->seq
11821             || ic->depth )) {
11822
11823               int size = AOP_SIZE(right) - 1;
11824
11825                 while (size--)
11826                   pic16_emitcode("decf","fsr0,f");
11827                   //pic16_emitcode("dec","%s",rname);
11828             }
11829         }
11830
11831     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11832     /* done */
11833 //release:
11834     pic16_freeAsmop(right,NULL,ic,TRUE);
11835     pic16_freeAsmop(result,NULL,ic,TRUE);
11836 }
11837
11838 /*-----------------------------------------------------------------*/
11839 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11840 /*-----------------------------------------------------------------*/
11841 static void genPagedPointerSet (operand *right,
11842                                operand *result, 
11843                                iCode *ic)
11844 {
11845     asmop *aop = NULL;
11846     regs *preg = NULL ;
11847     char *rname , *l;
11848     sym_link *retype;
11849        
11850     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11851
11852     retype= getSpec(operandType(right));
11853     
11854     pic16_aopOp(result,ic,FALSE);
11855     
11856     /* if the value is already in a pointer register
11857        then don't need anything more */
11858     if (!AOP_INPREG(AOP(result))) {
11859         /* otherwise get a free pointer register */
11860         aop = newAsmop(0);
11861         preg = getFreePtr(ic,&aop,FALSE);
11862         pic16_emitcode("mov","%s,%s",
11863                 preg->name,
11864                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11865         rname = preg->name ;
11866     } else
11867         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11868     
11869     pic16_freeAsmop(result,NULL,ic,TRUE);
11870     pic16_aopOp (right,ic,FALSE);
11871
11872     /* if bitfield then unpack the bits */
11873     if (IS_BITFIELD(retype)) 
11874         genPackBits (retype,result,right,rname,PPOINTER);
11875     else {
11876         /* we have can just get the values */
11877         int size = AOP_SIZE(right);
11878         int offset = 0 ;        
11879         
11880         while (size--) {
11881             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11882             
11883             MOVA(l);
11884             pic16_emitcode("movx","@%s,a",rname);
11885
11886             if (size)
11887                 pic16_emitcode("inc","%s",rname);
11888
11889             offset++;
11890         }
11891     }
11892     
11893     /* now some housekeeping stuff */
11894     if (aop) {
11895         /* we had to allocate for this iCode */
11896         pic16_freeAsmop(NULL,aop,ic,TRUE);
11897     } else { 
11898         /* we did not allocate which means left
11899            already in a pointer register, then
11900            if size > 0 && this could be used again
11901            we have to point it back to where it 
11902            belongs */
11903         if (AOP_SIZE(right) > 1 &&
11904             !OP_SYMBOL(result)->remat &&
11905             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11906               ic->depth )) {
11907             int size = AOP_SIZE(right) - 1;
11908             while (size--)
11909                 pic16_emitcode("dec","%s",rname);
11910         }
11911     }
11912
11913     /* done */
11914     pic16_freeAsmop(right,NULL,ic,TRUE);
11915     
11916         
11917 }
11918
11919 /*-----------------------------------------------------------------*/
11920 /* genFarPointerSet - set value from far space                     */
11921 /*-----------------------------------------------------------------*/
11922 static void genFarPointerSet (operand *right,
11923                               operand *result, iCode *ic)
11924 {
11925     int size, offset ;
11926     sym_link *retype = getSpec(operandType(right));
11927
11928     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11929     pic16_aopOp(result,ic,FALSE);
11930
11931     /* if the operand is already in dptr 
11932     then we do nothing else we move the value to dptr */
11933     if (AOP_TYPE(result) != AOP_STR) {
11934         /* if this is remateriazable */
11935         if (AOP_TYPE(result) == AOP_IMMD)
11936             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11937         else { /* we need to get it byte by byte */
11938             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11939             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11940             if (options.model == MODEL_FLAT24)
11941             {
11942                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11943             }
11944         }
11945     }
11946     /* so dptr know contains the address */
11947     pic16_freeAsmop(result,NULL,ic,TRUE);
11948     pic16_aopOp(right,ic,FALSE);
11949
11950     /* if bit then unpack */
11951     if (IS_BITFIELD(retype)) 
11952         genPackBits(retype,result,right,"dptr",FPOINTER);
11953     else {
11954         size = AOP_SIZE(right);
11955         offset = 0 ;
11956
11957         while (size--) {
11958             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11959             MOVA(l);
11960             pic16_emitcode("movx","@dptr,a");
11961             if (size)
11962                 pic16_emitcode("inc","dptr");
11963         }
11964     }
11965
11966     pic16_freeAsmop(right,NULL,ic,TRUE);
11967 }
11968
11969 /*-----------------------------------------------------------------*/
11970 /* genGenPointerSet - set value from generic pointer space         */
11971 /*-----------------------------------------------------------------*/
11972 #if 0
11973 static void genGenPointerSet (operand *right,
11974                               operand *result, iCode *ic)
11975 {
11976         int i, size, offset, lit;
11977         sym_link *retype = getSpec(operandType(right));
11978
11979         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11980
11981         pic16_aopOp(result,ic,FALSE);
11982         pic16_aopOp(right,ic,FALSE);
11983         size = AOP_SIZE(right);
11984         offset = 0;
11985
11986         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11987
11988         /* if the operand is already in dptr 
11989                 then we do nothing else we move the value to dptr */
11990         if (AOP_TYPE(result) != AOP_STR) {
11991                 /* if this is remateriazable */
11992                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11993                 // WARNING: anythig until "else" is untested!
11994                 if (AOP_TYPE(result) == AOP_IMMD) {
11995                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11996                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11997                         // load FSR0 from immediate
11998                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11999                         offset = 0;
12000                         while(size--) {
12001                                 if(size) {
12002                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12003                                 } else {
12004                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12005                                 }
12006                                 offset++;
12007                         }
12008                         goto release;
12009                 }
12010                 else { /* we need to get it byte by byte */
12011                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12012                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12013
12014                         // set up FSR0 with address of result
12015                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12016                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12017
12018                         /* hack hack! see if this the FSR. If so don't load W */
12019                         if(AOP_TYPE(right) != AOP_ACC) {
12020
12021                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12022
12023                                 if(AOP_TYPE(right) == AOP_LIT)
12024                                 {
12025                                         // copy literal
12026                                         // note: pic16_popGet handles sign extension
12027                                         for(i=0;i<size;i++) {
12028                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12029                                                 if(i < size-1)
12030                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12031                                                 else
12032                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12033                                         }
12034                                 } else {
12035                                         // copy regs
12036
12037                                         for(i=0;i<size;i++) {
12038                                                 if(i < size-1)
12039                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12040                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12041                                                 else
12042                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12043                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12044                                         }
12045                                 }
12046                                 goto release;
12047                         } 
12048                         // right = ACC
12049                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12050                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12051                         goto release;
12052         } // if (AOP_TYPE(result) != AOP_IMMD)
12053
12054         } // if (AOP_TYPE(result) != AOP_STR)
12055         /* so dptr know contains the address */
12056
12057
12058         /* if bit then unpack */
12059         if (IS_BITFIELD(retype)) 
12060                 genPackBits(retype,result,right,"dptr",GPOINTER);
12061         else {
12062                 size = AOP_SIZE(right);
12063                 offset = 0 ;
12064
12065                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12066
12067                 // set up FSR0 with address of result
12068                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12069                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12070         
12071                 while (size--) {
12072                         if (AOP_TYPE(right) == AOP_LIT) {
12073                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12074                                 if (size) {
12075                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12076                                 } else {
12077                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12078                                 }
12079                         } else { // no literal
12080                                 if(size) {
12081                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12082                                 } else {
12083                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12084                                 }
12085                         }
12086                         offset++;
12087                 }
12088         }
12089
12090         release:
12091         pic16_freeAsmop(right,NULL,ic,TRUE);
12092         pic16_freeAsmop(result,NULL,ic,TRUE);
12093 }
12094 #endif
12095
12096 static void genGenPointerSet (operand *right,
12097                               operand *result, iCode *ic)
12098 {
12099   int size;
12100   sym_link *retype = getSpec(operandType(right));
12101
12102     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12103
12104     pic16_aopOp(result,ic,FALSE);
12105     pic16_aopOp(right,ic,FALSE);
12106     size = AOP_SIZE(right);
12107
12108     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12109
12110
12111     /* if bit then unpack */
12112     if (IS_BITFIELD(retype)) {
12113 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12114       genPackBits(retype,result,right,"dptr",GPOINTER);
12115       goto release;
12116     }
12117
12118     size = AOP_SIZE(right);
12119
12120     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12121
12122
12123
12124     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12125
12126     /* value of right+0 is placed on stack, which will be retrieved
12127      * by the support function this restoring the stack. The important
12128      * thing is that there is no need to manually restore stack pointer
12129      * here */
12130     pushaop(AOP(right), 0);
12131 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12132     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12133     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12134     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12135     
12136     /* load address to write to in WREG:FSR0H:FSR0L */
12137     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12138                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12139     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12140                                 pic16_popCopyReg(&pic16_pc_prodl)));
12141     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12142     
12143     pic16_callGenericPointerRW(1, size);
12144
12145 release:
12146     pic16_freeAsmop(right,NULL,ic,TRUE);
12147     pic16_freeAsmop(result,NULL,ic,TRUE);
12148 }
12149
12150 /*-----------------------------------------------------------------*/
12151 /* genPointerSet - stores the value into a pointer location        */
12152 /*-----------------------------------------------------------------*/
12153 static void genPointerSet (iCode *ic)
12154 {    
12155   operand *right, *result ;
12156   sym_link *type, *etype;
12157   int p_type;
12158
12159     FENTRY;
12160
12161     right = IC_RIGHT(ic);
12162     result = IC_RESULT(ic) ;
12163
12164     /* depending on the type of pointer we need to
12165     move it to the correct pointer register */
12166     type = operandType(result);
12167     etype = getSpec(type);
12168     /* if left is of type of pointer then it is simple */
12169     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12170         p_type = DCL_TYPE(type);
12171     }
12172     else {
12173         /* we have to go by the storage class */
12174         p_type = PTR_TYPE(SPEC_OCLS(etype));
12175
12176 /*      if (SPEC_OCLS(etype)->codesp ) { */
12177 /*          p_type = CPOINTER ;  */
12178 /*      } */
12179 /*      else */
12180 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12181 /*              p_type = FPOINTER ; */
12182 /*          else */
12183 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12184 /*                  p_type = PPOINTER ; */
12185 /*              else */
12186 /*                  if (SPEC_OCLS(etype) == idata ) */
12187 /*                      p_type = IPOINTER ; */
12188 /*                  else */
12189 /*                      p_type = POINTER ; */
12190     }
12191
12192     /* now that we have the pointer type we assign
12193     the pointer values */
12194     switch (p_type) {
12195       case POINTER:
12196       case IPOINTER:
12197         genNearPointerSet (right,result,ic);
12198         break;
12199
12200       case PPOINTER:
12201         genPagedPointerSet (right,result,ic);
12202         break;
12203
12204       case FPOINTER:
12205         genFarPointerSet (right,result,ic);
12206         break;
12207         
12208       case GPOINTER:
12209         genGenPointerSet (right,result,ic);
12210         break;
12211
12212       default:
12213         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12214           "genPointerSet: illegal pointer type");
12215     }
12216 }
12217
12218 /*-----------------------------------------------------------------*/
12219 /* genIfx - generate code for Ifx statement                        */
12220 /*-----------------------------------------------------------------*/
12221 static void genIfx (iCode *ic, iCode *popIc)
12222 {
12223   operand *cond = IC_COND(ic);
12224   int isbit =0;
12225
12226     FENTRY;
12227
12228     pic16_aopOp(cond,ic,FALSE);
12229
12230     /* get the value into acc */
12231     if (AOP_TYPE(cond) != AOP_CRY)
12232       pic16_toBoolean(cond);
12233     else
12234       isbit = 1;
12235     /* the result is now in the accumulator */
12236     pic16_freeAsmop(cond,NULL,ic,TRUE);
12237
12238     /* if there was something to be popped then do it */
12239     if (popIc)
12240       genIpop(popIc);
12241
12242     /* if the condition is  a bit variable */
12243     if (isbit && IS_ITEMP(cond) && 
12244         SPIL_LOC(cond)) {
12245       genIfxJump(ic,"c");
12246       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12247     } else {
12248       if (isbit && !IS_ITEMP(cond))
12249         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12250         else
12251         genIfxJump(ic,"a");
12252     }
12253     ic->generated = 1;
12254 }
12255
12256 /*-----------------------------------------------------------------*/
12257 /* genAddrOf - generates code for address of                       */
12258 /*-----------------------------------------------------------------*/
12259 static void genAddrOf (iCode *ic)
12260 {
12261   operand *result, *left;
12262   int size;
12263   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12264   pCodeOp *pcop0, *pcop1, *pcop2;
12265
12266     FENTRY;
12267
12268     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12269
12270     sym = OP_SYMBOL( IC_LEFT(ic) );
12271     
12272     if(sym->onStack) {
12273       /* get address of symbol on stack */
12274       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12275 #if 0
12276       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12277                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12278 #endif
12279
12280       // operands on stack are accessible via "FSR2 + index" with index
12281       // starting at 2 for arguments and growing from 0 downwards for
12282       // local variables (index == 0 is not assigned so we add one here)
12283       {
12284         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12285         if (soffs <= 0) {
12286           assert (soffs < 0);
12287           soffs++;
12288         } // if
12289         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12290         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12291         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12292         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12293         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12294         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12295         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12296       }
12297
12298       goto release;
12299     }
12300         
12301 //      if(pic16_debug_verbose) {
12302 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12303 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12304 //      }
12305         
12306     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12307     size = AOP_SIZE(IC_RESULT(ic));
12308
12309     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12310     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12311     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12312         
12313     if (size == 3) {
12314       pic16_emitpcode(POC_MOVLW, pcop0);
12315       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12316       pic16_emitpcode(POC_MOVLW, pcop1);
12317       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12318       pic16_emitpcode(POC_MOVLW, pcop2);
12319       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12320     } else
12321     if (size == 2) {
12322       pic16_emitpcode(POC_MOVLW, pcop0);
12323       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12324       pic16_emitpcode(POC_MOVLW, pcop1);
12325     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12326     } else {
12327       pic16_emitpcode(POC_MOVLW, pcop0);
12328       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12329     }
12330
12331     pic16_freeAsmop(left, NULL, ic, FALSE);
12332 release:
12333     pic16_freeAsmop(result,NULL,ic,TRUE);
12334 }
12335
12336
12337 #if 0
12338 /*-----------------------------------------------------------------*/
12339 /* genFarFarAssign - assignment when both are in far space         */
12340 /*-----------------------------------------------------------------*/
12341 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12342 {
12343     int size = AOP_SIZE(right);
12344     int offset = 0;
12345     char *l ;
12346     /* first push the right side on to the stack */
12347     while (size--) {
12348         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12349         MOVA(l);
12350         pic16_emitcode ("push","acc");
12351     }
12352     
12353     pic16_freeAsmop(right,NULL,ic,FALSE);
12354     /* now assign DPTR to result */
12355     pic16_aopOp(result,ic,FALSE);
12356     size = AOP_SIZE(result);
12357     while (size--) {
12358         pic16_emitcode ("pop","acc");
12359         pic16_aopPut(AOP(result),"a",--offset);
12360     }
12361     pic16_freeAsmop(result,NULL,ic,FALSE);
12362         
12363 }
12364 #endif
12365
12366 /*-----------------------------------------------------------------*/
12367 /* genAssign - generate code for assignment                        */
12368 /*-----------------------------------------------------------------*/
12369 static void genAssign (iCode *ic)
12370 {
12371   operand *result, *right;
12372   int size, offset,know_W;
12373   unsigned long lit = 0L;
12374
12375   result = IC_RESULT(ic);
12376   right  = IC_RIGHT(ic) ;
12377
12378   FENTRY;
12379   
12380   /* if they are the same */
12381   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12382     return ;
12383
12384   /* reversed order operands are aopOp'ed so that result operand
12385    * is effective in case right is a stack symbol. This maneauver
12386    * allows to use the _G.resDirect flag later */
12387   pic16_aopOp(result,ic,TRUE);
12388   pic16_aopOp(right,ic,FALSE);
12389
12390   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12391
12392   /* if they are the same registers */
12393   if (pic16_sameRegs(AOP(right),AOP(result)))
12394     goto release;
12395
12396   /* if the result is a bit */
12397   if (AOP_TYPE(result) == AOP_CRY) {
12398     /* if the right size is a literal then
12399        we know what the value is */
12400     if (AOP_TYPE(right) == AOP_LIT) {
12401           
12402       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12403                   pic16_popGet(AOP(result),0));
12404
12405       if (((int) operandLitValue(right))) 
12406         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12407                        AOP(result)->aopu.aop_dir,
12408                        AOP(result)->aopu.aop_dir);
12409       else
12410         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12411                        AOP(result)->aopu.aop_dir,
12412                        AOP(result)->aopu.aop_dir);
12413       goto release;
12414     }
12415
12416     /* the right is also a bit variable */
12417     if (AOP_TYPE(right) == AOP_CRY) {
12418       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12419       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12420       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12421
12422       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12423                      AOP(result)->aopu.aop_dir,
12424                      AOP(result)->aopu.aop_dir);
12425       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12426                      AOP(right)->aopu.aop_dir,
12427                      AOP(right)->aopu.aop_dir);
12428       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12429                      AOP(result)->aopu.aop_dir,
12430                      AOP(result)->aopu.aop_dir);
12431       goto release ;
12432     }
12433
12434     /* we need to or */
12435     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12436     pic16_toBoolean(right);
12437     emitSKPZ;
12438     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12439     //pic16_aopPut(AOP(result),"a",0);
12440     goto release ;
12441   }
12442
12443   /* bit variables done */
12444   /* general case */
12445   size = AOP_SIZE(result);
12446   offset = 0 ;
12447
12448   if(AOP_TYPE(right) == AOP_LIT) {
12449         if(!IS_FLOAT(operandType( right )))
12450                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12451         else {
12452            union {
12453               unsigned long lit_int;
12454               float lit_float;
12455             } info;
12456         
12457                 /* take care if literal is a float */
12458                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12459                 lit = info.lit_int;
12460         }
12461   }
12462
12463 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12464 //                      sizeof(unsigned long int), sizeof(float));
12465
12466
12467   if (AOP_TYPE(right) == AOP_REG) {
12468     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12469     while (size--) {
12470       
12471       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12472     } // while
12473     goto release;
12474   }
12475
12476   if(AOP_TYPE(right) != AOP_LIT
12477         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12478         && !IS_FUNC(OP_SYM_TYPE(right))
12479         ) {
12480         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12481         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12482
12483         // set up table pointer
12484         if(is_LitOp(right)) {
12485 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12486                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12487                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12488                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12489                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12490                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12491                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12492         } else {
12493 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12494                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12495                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12496                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12497                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12498                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12499                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12500         }
12501
12502         size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
12503         while(size--) {
12504                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12505                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12506                         pic16_popGet(AOP(result),offset)));
12507                 offset++;
12508         }
12509
12510         size = getSize(OP_SYM_ETYPE(right));
12511         if(AOP_SIZE(result) > size) {
12512                 size = AOP_SIZE(result) - size;
12513                 while(size--) {
12514                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12515                         offset++;
12516                 }
12517         }
12518         goto release;
12519   }
12520
12521
12522
12523 #if 0
12524 /* VR - What is this?! */
12525   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12526     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12527     if(aopIdx(AOP(result),0) == 4) {
12528
12529       /* this is a workaround to save value of right into wreg too,
12530        * value of wreg is going to be used later */
12531       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12532       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12533       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12534       goto release;
12535     } else
12536 //      assert(0);
12537       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12538   }
12539 #endif
12540
12541   know_W=-1;
12542   while (size--) {
12543   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12544     if(AOP_TYPE(right) == AOP_LIT) {
12545       if(lit&0xff) {
12546         if(know_W != (lit&0xff))
12547           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12548         know_W = lit&0xff;
12549         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12550       } else
12551         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12552
12553       lit >>= 8;
12554
12555     } else if (AOP_TYPE(right) == AOP_CRY) {
12556       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12557       if(offset == 0) {
12558         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12559         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12560         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12561       }
12562     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12563         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12564         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12565     } else {
12566       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12567
12568       if(!_G.resDirect)         /* use this aopForSym feature */
12569         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12570     }
12571             
12572     offset++;
12573   }
12574   
12575  release:
12576   pic16_freeAsmop (right,NULL,ic,FALSE);
12577   pic16_freeAsmop (result,NULL,ic,TRUE);
12578 }   
12579
12580 /*-----------------------------------------------------------------*/
12581 /* genJumpTab - generates code for jump table                       */
12582 /*-----------------------------------------------------------------*/
12583 static void genJumpTab (iCode *ic)
12584 {
12585   symbol *jtab;
12586   char *l;
12587   pCodeOp *jt_offs;
12588   pCodeOp *jt_offs_hi;
12589   pCodeOp *jt_label;
12590
12591     FENTRY;
12592
12593     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12594     /* get the condition into accumulator */
12595     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12596     MOVA(l);
12597     /* multiply by three */
12598     pic16_emitcode("add","a,acc");
12599     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12600
12601     jtab = newiTempLabel(NULL);
12602     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12603     pic16_emitcode("jmp","@a+dptr");
12604     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12605
12606 #if 0
12607     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12608     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12609     emitSKPNC;
12610     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12611     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12612     pic16_emitpLabel(jtab->key);
12613
12614 #else
12615
12616     jt_offs = pic16_popGetTempReg(0);
12617     jt_offs_hi = pic16_popGetTempReg(1);
12618     jt_label = pic16_popGetLabel (jtab->key);
12619     //fprintf (stderr, "Creating jump table...\n");
12620
12621     // calculate offset into jump table (idx * sizeof (GOTO))
12622     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12623     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12624     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12625     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12626     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12627     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12628     pic16_emitpcode(POC_MOVWF , jt_offs);
12629
12630     // prepare PCLATx (set to first entry in jump table)
12631     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12632     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12633     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12634     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12635     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12636
12637     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12638     pic16_emitpcode(POC_ADDWF , jt_offs);
12639     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12640     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12641     emitSKPNC;
12642     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12643
12644     // release temporaries and prepare jump into table (new PCL --> WREG)
12645     pic16_emitpcode(POC_MOVFW , jt_offs);
12646     pic16_popReleaseTempReg (jt_offs_hi, 1);
12647     pic16_popReleaseTempReg (jt_offs, 0);
12648
12649     // jump into the table
12650     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12651
12652     pic16_emitpLabelFORCE(jtab->key);
12653 #endif
12654
12655     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12656 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12657
12658     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12659     /* now generate the jump labels */
12660     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12661          jtab = setNextItem(IC_JTLABELS(ic))) {
12662 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12663         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12664         
12665     }
12666     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12667
12668 }
12669
12670 /*-----------------------------------------------------------------*/
12671 /* genMixedOperation - gen code for operators between mixed types  */
12672 /*-----------------------------------------------------------------*/
12673 /*
12674   TSD - Written for the PIC port - but this unfortunately is buggy.
12675   This routine is good in that it is able to efficiently promote 
12676   types to different (larger) sizes. Unfortunately, the temporary
12677   variables that are optimized out by this routine are sometimes
12678   used in other places. So until I know how to really parse the 
12679   iCode tree, I'm going to not be using this routine :(.
12680 */
12681 static int genMixedOperation (iCode *ic)
12682 {
12683 #if 0
12684   operand *result = IC_RESULT(ic);
12685   sym_link *ctype = operandType(IC_LEFT(ic));
12686   operand *right = IC_RIGHT(ic);
12687   int ret = 0;
12688   int big,small;
12689   int offset;
12690
12691   iCode *nextic;
12692   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12693
12694   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12695
12696   nextic = ic->next;
12697   if(!nextic)
12698     return 0;
12699
12700   nextright = IC_RIGHT(nextic);
12701   nextleft  = IC_LEFT(nextic);
12702   nextresult = IC_RESULT(nextic);
12703
12704   pic16_aopOp(right,ic,FALSE);
12705   pic16_aopOp(result,ic,FALSE);
12706   pic16_aopOp(nextright,  nextic, FALSE);
12707   pic16_aopOp(nextleft,   nextic, FALSE);
12708   pic16_aopOp(nextresult, nextic, FALSE);
12709
12710   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12711
12712     operand *t = right;
12713     right = nextright;
12714     nextright = t; 
12715
12716     pic16_emitcode(";remove right +","");
12717
12718   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12719 /*
12720     operand *t = right;
12721     right = nextleft;
12722     nextleft = t; 
12723 */
12724     pic16_emitcode(";remove left +","");
12725   } else
12726     return 0;
12727
12728   big = AOP_SIZE(nextleft);
12729   small = AOP_SIZE(nextright);
12730
12731   switch(nextic->op) {
12732
12733   case '+':
12734     pic16_emitcode(";optimize a +","");
12735     /* if unsigned or not an integral type */
12736     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12737       pic16_emitcode(";add a bit to something","");
12738     } else {
12739
12740       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12741
12742       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12743         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12744         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12745       } else
12746         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12747
12748       offset = 0;
12749       while(--big) {
12750
12751         offset++;
12752
12753         if(--small) {
12754           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12755             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12756             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12757           }
12758
12759           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12760           emitSKPNC;
12761           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12762                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12763                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12764           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12765           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12766
12767         } else {
12768           pic16_emitcode("rlf","known_zero,w");
12769
12770           /*
12771             if right is signed
12772               btfsc  right,7
12773                addlw ff
12774           */
12775           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12776             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12777             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12778           } else {
12779             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12780           }
12781         }
12782       }
12783       ret = 1;
12784     }
12785   }
12786   ret = 1;
12787
12788 release:
12789   pic16_freeAsmop(right,NULL,ic,TRUE);
12790   pic16_freeAsmop(result,NULL,ic,TRUE);
12791   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12792   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12793   if(ret)
12794     nextic->generated = 1;
12795
12796   return ret;
12797 #else
12798   return 0;
12799 #endif
12800 }
12801 /*-----------------------------------------------------------------*/
12802 /* genCast - gen code for casting                                  */
12803 /*-----------------------------------------------------------------*/
12804 static void genCast (iCode *ic)
12805 {
12806   operand *result = IC_RESULT(ic);
12807   sym_link *ctype = operandType(IC_LEFT(ic));
12808   sym_link *rtype = operandType(IC_RIGHT(ic));
12809   sym_link *restype = operandType(IC_RESULT(ic));
12810   operand *right = IC_RIGHT(ic);
12811   int size, offset ;
12812
12813
12814     FENTRY;
12815
12816         /* if they are equivalent then do nothing */
12817 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12818 //              return ;
12819
12820         pic16_aopOp(result,ic,FALSE);
12821         pic16_aopOp(right,ic,FALSE) ;
12822
12823         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12824
12825
12826         /* if the result is a bit */
12827         if (AOP_TYPE(result) == AOP_CRY) {
12828         
12829                 /* if the right size is a literal then
12830                  * we know what the value is */
12831                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12832
12833                 if (AOP_TYPE(right) == AOP_LIT) {
12834                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12835                                 pic16_popGet(AOP(result),0));
12836
12837                         if (((int) operandLitValue(right))) 
12838                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12839                                         AOP(result)->aopu.aop_dir,
12840                                         AOP(result)->aopu.aop_dir);
12841                         else
12842                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12843                                         AOP(result)->aopu.aop_dir,
12844                                         AOP(result)->aopu.aop_dir);
12845                         goto release;
12846                 }
12847
12848                 /* the right is also a bit variable */
12849                 if (AOP_TYPE(right) == AOP_CRY) {
12850                         emitCLRC;
12851                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12852
12853                         pic16_emitcode("clrc","");
12854                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12855                                 AOP(right)->aopu.aop_dir,
12856                                 AOP(right)->aopu.aop_dir);
12857                         pic16_aopPut(AOP(result),"c",0);
12858                         goto release ;
12859                 }
12860
12861                 /* we need to or */
12862                 if (AOP_TYPE(right) == AOP_REG) {
12863                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12864                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12865                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12866                 }
12867                 pic16_toBoolean(right);
12868                 pic16_aopPut(AOP(result),"a",0);
12869                 goto release ;
12870         }
12871
12872         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12873           int offset = 1;
12874
12875                 size = AOP_SIZE(result);
12876
12877                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12878
12879                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12880                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12881                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12882
12883                 while (size--)
12884                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12885
12886                 goto release;
12887         }
12888
12889         if(IS_BITFIELD(getSpec(restype))
12890           && IS_BITFIELD(getSpec(rtype))) {
12891           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12892         }
12893
12894         /* if they are the same size : or less */
12895         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12896
12897                 /* if they are in the same place */
12898                 if (pic16_sameRegs(AOP(right),AOP(result)))
12899                         goto release;
12900
12901                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12902 #if 0
12903                 if (IS_PTR_CONST(rtype))
12904 #else
12905                 if (IS_CODEPTR(rtype))
12906 #endif
12907                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12908
12909 #if 0
12910                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12911 #else
12912                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12913 #endif
12914                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12915
12916 #if 0
12917                 if(AOP_TYPE(right) == AOP_IMMD) {
12918                   pCodeOp *pcop0, *pcop1, *pcop2;
12919                   symbol *sym = OP_SYMBOL( right );
12920
12921                         size = AOP_SIZE(result);
12922                         /* low */
12923                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12924                         /* high */
12925                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12926                         /* upper */
12927                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12928         
12929                         if (size == 3) {
12930                                 pic16_emitpcode(POC_MOVLW, pcop0);
12931                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12932                                 pic16_emitpcode(POC_MOVLW, pcop1);
12933                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12934                                 pic16_emitpcode(POC_MOVLW, pcop2);
12935                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12936                         } else
12937                         if (size == 2) {
12938                                 pic16_emitpcode(POC_MOVLW, pcop0);
12939                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12940                                 pic16_emitpcode(POC_MOVLW, pcop1);
12941                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12942                         } else {
12943                                 pic16_emitpcode(POC_MOVLW, pcop0);
12944                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12945                         }
12946                 } else
12947 #endif
12948                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12949                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12950                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12951                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12952                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12953                         if(AOP_SIZE(result) <2)
12954                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12955                 } else {
12956                         /* if they in different places then copy */
12957                         size = AOP_SIZE(result);
12958                         offset = 0 ;
12959                         while (size--) {
12960                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12961                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12962                                 offset++;
12963                         }
12964                 }
12965                 goto release;
12966         }
12967
12968         /* if the result is of type pointer */
12969         if (IS_PTR(ctype)) {
12970           int p_type;
12971           sym_link *type = operandType(right);
12972           sym_link *etype = getSpec(type);
12973
12974                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
12975
12976                 /* pointer to generic pointer */
12977                 if (IS_GENPTR(ctype)) {
12978                   char *l = zero;
12979             
12980                         if (IS_PTR(type)) 
12981                                 p_type = DCL_TYPE(type);
12982                         else {
12983                 /* we have to go by the storage class */
12984                 p_type = PTR_TYPE(SPEC_OCLS(etype));
12985
12986 /*              if (SPEC_OCLS(etype)->codesp )  */
12987 /*                  p_type = CPOINTER ;  */
12988 /*              else */
12989 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12990 /*                      p_type = FPOINTER ; */
12991 /*                  else */
12992 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12993 /*                          p_type = PPOINTER; */
12994 /*                      else */
12995 /*                          if (SPEC_OCLS(etype) == idata ) */
12996 /*                              p_type = IPOINTER ; */
12997 /*                          else */
12998 /*                              p_type = POINTER ; */
12999             }
13000                 
13001             /* the first two bytes are known */
13002       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13003             size = GPTRSIZE - 1; 
13004             offset = 0 ;
13005             while (size--) {
13006               if(offset < AOP_SIZE(right)) {
13007                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13008                 mov2f(AOP(result), AOP(right), offset);
13009 /*
13010                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13011                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13012                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13013                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13014                 } else { 
13015                   
13016                   pic16_aopPut(AOP(result),
13017                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13018                          offset);
13019                 }
13020 */
13021               } else 
13022                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13023               offset++;
13024             }
13025             /* the last byte depending on type */
13026             switch (p_type) {
13027             case IPOINTER:
13028             case POINTER:
13029                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13030                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13031 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13032                 break;
13033
13034             case CPOINTER:
13035                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13036                 break;
13037
13038             case FPOINTER:
13039               pic16_emitcode(";BUG!? ","%d",__LINE__);
13040                 l = one;
13041                 break;
13042             case PPOINTER:
13043               pic16_emitcode(";BUG!? ","%d",__LINE__);
13044                 l = "#0x03";
13045                 break;
13046
13047             case GPOINTER:
13048                 if (GPTRSIZE > AOP_SIZE(right)) {
13049                   // assume data pointer... THIS MIGHT BE WRONG!
13050                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13051                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13052                 } else {
13053                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13054                 }
13055               break;
13056               
13057             default:
13058                 /* this should never happen */
13059                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13060                        "got unknown pointer type");
13061                 exit(1);
13062             }
13063             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13064             goto release ;
13065         }
13066         
13067         
13068         assert( 0 );
13069         /* just copy the pointers */
13070         size = AOP_SIZE(result);
13071         offset = 0 ;
13072         while (size--) {
13073             pic16_aopPut(AOP(result),
13074                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13075                    offset);
13076             offset++;
13077         }
13078         goto release ;
13079     }
13080     
13081
13082
13083     /* so we now know that the size of destination is greater
13084     than the size of the source.
13085     Now, if the next iCode is an operator then we might be
13086     able to optimize the operation without performing a cast.
13087     */
13088     if(genMixedOperation(ic))
13089       goto release;
13090
13091     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13092     
13093     /* we move to result for the size of source */
13094     size = AOP_SIZE(right);
13095     offset = 0 ;
13096
13097     while (size--) {
13098       if(!_G.resDirect)
13099         mov2f(AOP(result), AOP(right), offset);
13100       offset++;
13101     }
13102
13103     /* now depending on the sign of the destination */
13104     size = AOP_SIZE(result) - AOP_SIZE(right);
13105     /* if unsigned or not an integral type */
13106     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13107       while (size--)
13108         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13109     } else {
13110       /* we need to extend the sign :( */
13111
13112       if(size == 1) {
13113         /* Save one instruction of casting char to int */
13114         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13115         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13116         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
13117       } else {
13118         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13119
13120         if(offset)
13121           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13122         else
13123           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13124         
13125         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13126
13127         while (size--)
13128           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13129       }
13130     }
13131
13132 release:
13133     pic16_freeAsmop(right,NULL,ic,TRUE);
13134     pic16_freeAsmop(result,NULL,ic,TRUE);
13135
13136 }
13137
13138 /*-----------------------------------------------------------------*/
13139 /* genDjnz - generate decrement & jump if not zero instrucion      */
13140 /*-----------------------------------------------------------------*/
13141 static int genDjnz (iCode *ic, iCode *ifx)
13142 {
13143     symbol *lbl, *lbl1;
13144     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13145
13146     if (!ifx)
13147         return 0;
13148     
13149     /* if the if condition has a false label
13150        then we cannot save */
13151     if (IC_FALSE(ifx))
13152         return 0;
13153
13154     /* if the minus is not of the form 
13155        a = a - 1 */
13156     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13157         !IS_OP_LITERAL(IC_RIGHT(ic)))
13158         return 0;
13159
13160     if (operandLitValue(IC_RIGHT(ic)) != 1)
13161         return 0;
13162
13163     /* if the size of this greater than one then no
13164        saving */
13165     if (getSize(operandType(IC_RESULT(ic))) > 1)
13166         return 0;
13167
13168     /* otherwise we can save BIG */
13169     lbl = newiTempLabel(NULL);
13170     lbl1= newiTempLabel(NULL);
13171
13172     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13173     
13174     if (IS_AOP_PREG(IC_RESULT(ic))) {
13175         pic16_emitcode("dec","%s",
13176                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13177         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13178         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13179     } else {    
13180
13181
13182       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13183       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13184
13185       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13186       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13187
13188     }
13189     
13190     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13191     ifx->generated = 1;
13192     return 1;
13193 }
13194
13195 /*-----------------------------------------------------------------*/
13196 /* genReceive - generate code for a receive iCode                  */
13197 /*-----------------------------------------------------------------*/
13198 static void genReceive (iCode *ic)
13199 {    
13200
13201   FENTRY;
13202
13203 #if 0
13204   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13205         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13206 #endif
13207 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13208
13209   if (isOperandInFarSpace(IC_RESULT(ic))
13210       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13211           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13212
13213     int size = getSize(operandType(IC_RESULT(ic)));
13214     int offset =  pic16_fReturnSizePic - size;
13215
13216       assert( 0 );
13217       while (size--) {
13218         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13219                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13220                       offset++;
13221         }
13222
13223       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13224
13225       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13226       size = AOP_SIZE(IC_RESULT(ic));
13227       offset = 0;
13228       while (size--) {
13229         pic16_emitcode ("pop","acc");
13230         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13231       }
13232   } else {
13233     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13234     _G.accInUse++;
13235     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13236     _G.accInUse--;
13237
13238     /* set pseudo stack pointer to where it should be - dw*/
13239     GpsuedoStkPtr = ic->parmBytes;
13240
13241     /* setting GpsuedoStkPtr has side effects here: */
13242     assignResultValue(IC_RESULT(ic), 0);
13243   }
13244
13245   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13246 }
13247
13248 /*-----------------------------------------------------------------*/
13249 /* genDummyRead - generate code for dummy read of volatiles        */
13250 /*-----------------------------------------------------------------*/
13251 static void
13252 genDummyRead (iCode * ic)
13253 {
13254   operand *op;
13255   int i;
13256
13257   op = IC_RIGHT(ic);
13258   if (op && IS_SYMOP(op)) {
13259     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13260       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13261       return;
13262     }
13263     pic16_aopOp (op, ic, FALSE);
13264     for (i=0; i < AOP_SIZE(op); i++) {
13265       // may need to protect this from the peepholer -- this is not nice but works...
13266       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13267       pic16_mov2w (AOP(op),i);
13268       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13269     } // for i
13270     pic16_freeAsmop (op, NULL, ic, TRUE);
13271   } else if (op) {
13272     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13273   } // if
13274 }
13275
13276 /*-----------------------------------------------------------------*/
13277 /* genpic16Code - generate code for pic16 based controllers        */
13278 /*-----------------------------------------------------------------*/
13279 /*
13280  * At this point, ralloc.c has gone through the iCode and attempted
13281  * to optimize in a way suitable for a PIC. Now we've got to generate
13282  * PIC instructions that correspond to the iCode.
13283  *
13284  * Once the instructions are generated, we'll pass through both the
13285  * peep hole optimizer and the pCode optimizer.
13286  *-----------------------------------------------------------------*/
13287
13288 void genpic16Code (iCode *lic)
13289 {
13290   iCode *ic;
13291   int cln = 0;
13292
13293     lineHead = lineCurr = NULL;
13294
13295     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13296     pic16_addpBlock(pb);
13297
13298 #if 0
13299     /* if debug information required */
13300     if (options.debug && currFunc) {
13301       if (currFunc) {
13302         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13303       }
13304     }
13305 #endif
13306
13307     for (ic = lic ; ic ; ic = ic->next ) {
13308
13309       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13310       if ( cln != ic->lineno ) {
13311         if ( options.debug ) {
13312           debugFile->writeCLine (ic);
13313         }
13314         
13315         if(!options.noCcodeInAsm) {
13316           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13317               printCLine(ic->filename, ic->lineno)));
13318         }
13319
13320         cln = ic->lineno ;
13321       }
13322         
13323       if(options.iCodeInAsm) {
13324         char *l;
13325
13326           /* insert here code to print iCode as comment */
13327           l = Safe_strdup(printILine(ic));
13328           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13329       }
13330         
13331       /* if the result is marked as
13332        * spilt and rematerializable or code for
13333        * this has already been generated then
13334        * do nothing */
13335       if (resultRemat(ic) || ic->generated ) 
13336         continue ;
13337         
13338       /* depending on the operation */
13339       switch (ic->op) {
13340         case '!' :
13341           pic16_genNot(ic);
13342           break;
13343             
13344         case '~' :
13345           pic16_genCpl(ic);
13346           break;
13347             
13348         case UNARYMINUS:
13349           genUminus (ic);
13350           break;
13351             
13352         case IPUSH:
13353           genIpush (ic);
13354           break;
13355             
13356         case IPOP:
13357           /* IPOP happens only when trying to restore a 
13358            * spilt live range, if there is an ifx statement
13359            * following this pop then the if statement might
13360            * be using some of the registers being popped which
13361            * would destroy the contents of the register so
13362            * we need to check for this condition and handle it */
13363            if (ic->next
13364              && ic->next->op == IFX
13365              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13366                genIfx (ic->next,ic);
13367           else
13368             genIpop (ic);
13369           break; 
13370             
13371         case CALL:
13372           genCall (ic);
13373           break;
13374             
13375         case PCALL:
13376           genPcall (ic);
13377           break;
13378             
13379         case FUNCTION:
13380           genFunction (ic);
13381           break;
13382             
13383         case ENDFUNCTION:
13384           genEndFunction (ic);
13385           break;
13386             
13387         case RETURN:
13388           genRet (ic);
13389           break;
13390             
13391         case LABEL:
13392           genLabel (ic);
13393           break;
13394             
13395         case GOTO:
13396           genGoto (ic);
13397           break;
13398             
13399         case '+' :
13400           pic16_genPlus (ic) ;
13401           break;
13402             
13403         case '-' :
13404           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13405             pic16_genMinus (ic);
13406           break;
13407
13408         case '*' :
13409           genMult (ic);
13410           break;
13411             
13412         case '/' :
13413           genDiv (ic) ;
13414           break;
13415             
13416         case '%' :
13417           genMod (ic);
13418           break;
13419             
13420         case '>' :
13421           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13422           break;
13423             
13424         case '<' :
13425           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13426           break;
13427             
13428         case LE_OP:
13429         case GE_OP:
13430         case NE_OP:
13431           /* note these two are xlated by algebraic equivalence
13432            * during parsing SDCC.y */
13433           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13434             "got '>=' or '<=' shouldn't have come here");
13435           break;
13436
13437         case EQ_OP:
13438           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13439           break;            
13440             
13441         case AND_OP:
13442           genAndOp (ic);
13443           break;
13444             
13445         case OR_OP:
13446           genOrOp (ic);
13447           break;
13448             
13449         case '^' :
13450           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13451           break;
13452             
13453         case '|' :
13454           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13455           break;
13456             
13457         case BITWISEAND:
13458           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13459           break;
13460             
13461         case INLINEASM:
13462           genInline (ic);
13463           break;
13464             
13465         case RRC:
13466           genRRC (ic);
13467           break;
13468             
13469         case RLC:
13470           genRLC (ic);
13471           break;
13472             
13473         case GETHBIT:
13474           genGetHbit (ic);
13475           break;
13476             
13477         case LEFT_OP:
13478           genLeftShift (ic);
13479           break;
13480             
13481         case RIGHT_OP:
13482           genRightShift (ic);
13483           break;
13484             
13485         case GET_VALUE_AT_ADDRESS:
13486           genPointerGet(ic);
13487           break;
13488             
13489         case '=' :
13490           if (POINTER_SET(ic))
13491             genPointerSet(ic);
13492           else
13493             genAssign(ic);
13494           break;
13495             
13496         case IFX:
13497           genIfx (ic,NULL);
13498           break;
13499             
13500         case ADDRESS_OF:
13501           genAddrOf (ic);
13502           break;
13503             
13504         case JUMPTABLE:
13505           genJumpTab (ic);
13506           break;
13507             
13508         case CAST:
13509           genCast (ic);
13510           break;
13511             
13512         case RECEIVE:
13513           genReceive(ic);
13514           break;
13515             
13516         case SEND:
13517           addSet(&_G.sendSet,ic);
13518           break;
13519
13520         case DUMMY_READ_VOLATILE:
13521           genDummyRead (ic);
13522           break;
13523
13524         default :
13525           ic = ic;
13526       }
13527     }
13528
13529
13530     /* now we are ready to call the
13531        peep hole optimizer */
13532     if (!options.nopeep)
13533       peepHole (&lineHead);
13534
13535     /* now do the actual printing */
13536     printLine (lineHead, codeOutFile);
13537
13538 #ifdef PCODE_DEBUG
13539     DFPRINTF((stderr,"printing pBlock\n\n"));
13540     pic16_printpBlock(stdout,pb);
13541 #endif
13542
13543     return;
13544 }
13545