* src/pic16/gen.c (genInline), src/pic16/main.c (_process_pragma),
[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   memcpy (pcor, pc, sizeof (pCodeOpReg));
1795   pcor->r->wasUsed = 1;
1796   
1797   //pcor->pcop.type = pc->pcop.type;
1798   if(pc->pcop.name) {
1799     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1800       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1801   } else
1802     pcor->pcop.name = NULL;
1803
1804   //pcor->r = pc->r;
1805   //pcor->rIdx = pc->rIdx;
1806   //pcor->r->wasUsed=1;
1807   //pcor->instance = pc->instance;
1808
1809 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1810
1811   return PCOP(pcor);
1812 }
1813
1814 /*-----------------------------------------------------------------*/
1815 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1816 /*-----------------------------------------------------------------*/
1817 pCodeOp *pic16_popGetLit(int lit)
1818 {
1819   return pic16_newpCodeOpLit(lit);
1820 }
1821
1822 /*-----------------------------------------------------------------*/
1823 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1824 /*-----------------------------------------------------------------*/
1825 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1826 {
1827   return pic16_newpCodeOpLit2(lit, arg2);
1828 }
1829
1830
1831 /*-----------------------------------------------------------------*/
1832 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1833 /*-----------------------------------------------------------------*/
1834 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1835 {
1836   return pic16_newpCodeOpImmd(name, offset,index, 0);
1837 }
1838
1839
1840 /*-----------------------------------------------------------------*/
1841 /* pic16_popGet - asm operator to pcode operator conversion              */
1842 /*-----------------------------------------------------------------*/
1843 pCodeOp *pic16_popGetWithString(char *str)
1844 {
1845   pCodeOp *pcop;
1846
1847
1848   if(!str) {
1849     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1850     exit (1);
1851   }
1852
1853   pcop = pic16_newpCodeOp(str,PO_STR);
1854
1855   return pcop;
1856 }
1857
1858 /*-----------------------------------------------------------------*/
1859 /* pic16_popRegFromString -                                        */
1860 /*-----------------------------------------------------------------*/
1861 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1862 {
1863
1864   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1865   pcop->type = PO_DIR;
1866
1867   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1868   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1869
1870   if(!str)
1871     str = "BAD_STRING";
1872
1873   pcop->name = Safe_calloc(1,strlen(str)+1);
1874   strcpy(pcop->name,str);
1875
1876   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1877
1878   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1879
1880   /* make sure that register doesn't exist,
1881    * and operand isn't NULL
1882    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1883   if((PCOR(pcop)->r == NULL) 
1884     && (op)
1885     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1886 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1887 //              __FUNCTION__, __LINE__, str, size, offset);
1888
1889     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1890     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1891
1892   }
1893   PCOR(pcop)->instance = offset;
1894
1895   return pcop;
1896 }
1897
1898 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1899 {
1900   pCodeOp *pcop;
1901
1902 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1903
1904         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1905         PCOR(pcop)->rIdx = rIdx;
1906         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1907
1908         PCOR(pcop)->r->isFree = 0;
1909         PCOR(pcop)->r->wasUsed = 1;
1910
1911         pcop->type = PCOR(pcop)->r->pc_type;
1912
1913   return pcop;
1914 }
1915
1916 /*---------------------------------------------------------------------------------*/
1917 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1918 /*                 VR 030601                                                       */
1919 /*---------------------------------------------------------------------------------*/
1920 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1921 {
1922   pCodeOpReg2 *pcop2;
1923   pCodeOp *temp;
1924   
1925         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1926
1927         /* comment the following check, so errors to throw up */
1928 //      if(!pcop2)return NULL;
1929
1930         temp = pic16_popGet(aop_dst, offset);
1931         pcop2->pcop2 = temp;
1932         
1933   return PCOP(pcop2);
1934 }
1935
1936
1937
1938 /*--------------------------------------------------------------------------------.-*/
1939 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1940 /*                  VR 030601 , adapted by Hans Dorn                                */
1941 /*--------------------------------------------------------------------------------.-*/
1942 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1943 {
1944   pCodeOpReg2 *pcop2;
1945  
1946         pcop2 = (pCodeOpReg2 *)src;
1947         pcop2->pcop2 = dst;
1948         
1949         return PCOP(pcop2);
1950 }
1951
1952
1953
1954 /*---------------------------------------------------------------------------------*/
1955 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1956 /*                     movff instruction                                           */
1957 /*---------------------------------------------------------------------------------*/
1958 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1959 {
1960   pCodeOpReg2 *pcop2;
1961
1962         if(!noalloc) {
1963                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1964                 pcop2->pcop2 = pic16_popCopyReg(dst);
1965         } else {
1966                 /* the pCodeOp may be already allocated */
1967                 pcop2 = (pCodeOpReg2 *)(src);
1968                 pcop2->pcop2 = (pCodeOp *)(dst);
1969         }
1970
1971   return PCOP(pcop2);
1972 }
1973
1974
1975 /*-----------------------------------------------------------------*/
1976 /* pic16_popGet - asm operator to pcode operator conversion              */
1977 /*-----------------------------------------------------------------*/
1978 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1979 {
1980   //char *s = buffer ;
1981   char *rs;
1982   pCodeOp *pcop;
1983
1984     FENTRY2;
1985     /* offset is greater than
1986     size then zero */
1987
1988 //    if (offset > (aop->size - 1) &&
1989 //        aop->type != AOP_LIT)
1990 //      return NULL;  //zero;
1991
1992     /* depending on type */
1993     switch (aop->type) {
1994         
1995     case AOP_R0:
1996     case AOP_R1:
1997     case AOP_DPTR:
1998     case AOP_DPTR2:
1999         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2000         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2001         assert( 0 );
2002         return NULL;
2003
2004
2005     case AOP_FSR0:
2006     case AOP_FSR2:
2007       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2008       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
2009       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2010       PCOR(pcop)->r->wasUsed = 1;
2011       PCOR(pcop)->r->isFree = 0;
2012       
2013       PCOR(pcop)->instance = offset;
2014       pcop->type = PCOR(pcop)->r->pc_type;
2015       return (pcop);
2016
2017     case AOP_IMMD:
2018       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2019       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2020
2021     case AOP_STA:
2022       /* pCodeOp is already allocated from aopForSym */
2023         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2024         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2025           
2026       return (pcop);
2027       
2028     case AOP_ACC:
2029       {
2030         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
2031
2032         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2033
2034         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2035         
2036         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2037         PCOR(pcop)->rIdx = rIdx;
2038         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2039         PCOR(pcop)->r->wasUsed=1;
2040         PCOR(pcop)->r->isFree=0;
2041
2042         PCOR(pcop)->instance = offset;
2043         pcop->type = PCOR(pcop)->r->pc_type;
2044 //      rs = aop->aopu.aop_reg[offset]->name;
2045 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2046         return pcop;
2047
2048
2049 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2050 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2051
2052 //      assert( 0 );
2053       }
2054         
2055     case AOP_DIR:
2056       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2057       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2058         
2059 #if 0
2060     case AOP_PAGED:
2061       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2062       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2063 #endif
2064
2065     case AOP_REG:
2066       {
2067         int rIdx;
2068         assert (aop && aop->aopu.aop_reg[offset] != NULL);
2069         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2070
2071         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2072         
2073         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2074 //      pcop->type = PO_GPR_REGISTER;
2075         PCOR(pcop)->rIdx = rIdx;
2076         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
2077         PCOR(pcop)->r->wasUsed=1;
2078         PCOR(pcop)->r->isFree=0;
2079
2080         PCOR(pcop)->instance = offset;
2081         pcop->type = PCOR(pcop)->r->pc_type;
2082         
2083         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2084         rs = aop->aopu.aop_reg[offset]->name;
2085         DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2086         return pcop;
2087       }
2088
2089     case AOP_CRY:
2090         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2091
2092       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2093       PCOR(pcop)->instance = offset;
2094       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2095       //if(PCOR(pcop)->r == NULL)
2096       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2097       return pcop;
2098         
2099     case AOP_LIT:
2100         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2101       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2102
2103     case AOP_STR:
2104       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2105       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2106
2107       /*
2108       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2109       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2110       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2111       pcop->type = PCOR(pcop)->r->pc_type;
2112       pcop->name = PCOR(pcop)->r->name;
2113
2114       return pcop;
2115       */
2116
2117     case AOP_PCODE:
2118       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2119                           __LINE__, 
2120                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2121       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2122       switch( aop->aopu.pcop->type ) {
2123         case PO_DIR: PCOR(pcop)->instance += offset; break;
2124         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2125         case PO_WREG:
2126             assert (offset==0);
2127             break;
2128         default:
2129           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2130           assert( 0 );  /* should never reach here */;
2131       }
2132       return pcop;
2133     }
2134
2135     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2136            "pic16_popGet got unsupported aop->type");
2137     exit(0);
2138 }
2139 /*-----------------------------------------------------------------*/
2140 /* pic16_aopPut - puts a string for a aop                                */
2141 /*-----------------------------------------------------------------*/
2142 void pic16_aopPut (asmop *aop, char *s, int offset)
2143 {
2144     char *d = buffer ;
2145     symbol *lbl ;
2146
2147     return;
2148
2149     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2150
2151     if (aop->size && offset > ( aop->size - 1)) {
2152         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2153                "pic16_aopPut got offset > aop->size");
2154         exit(0);
2155     }
2156
2157     /* will assign value to value */
2158     /* depending on where it is ofcourse */
2159     switch (aop->type) {
2160     case AOP_DIR:
2161       if (offset) {
2162         sprintf(d,"(%s + %d)",
2163                 aop->aopu.aop_dir,offset);
2164         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2165
2166       } else
2167             sprintf(d,"%s",aop->aopu.aop_dir);
2168         
2169         if (strcmp(d,s)) {
2170           DEBUGpic16_emitcode(";","%d",__LINE__);
2171           if(strcmp(s,"W"))
2172             pic16_emitcode("movf","%s,w",s);
2173           pic16_emitcode("movwf","%s",d);
2174
2175           if(strcmp(s,"W")) {
2176             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2177             if(offset >= aop->size) {
2178               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2179               break;
2180             } else
2181               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2182           }
2183
2184           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2185
2186
2187         }
2188         break;
2189         
2190     case AOP_REG:
2191       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2192         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2193           /*
2194             if (*s == '@'           ||
2195                 strcmp(s,"r0") == 0 ||
2196                 strcmp(s,"r1") == 0 ||
2197                 strcmp(s,"r2") == 0 ||
2198                 strcmp(s,"r3") == 0 ||
2199                 strcmp(s,"r4") == 0 ||
2200                 strcmp(s,"r5") == 0 ||
2201                 strcmp(s,"r6") == 0 || 
2202                 strcmp(s,"r7") == 0 )
2203                 pic16_emitcode("mov","%s,%s  ; %d",
2204                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2205             else
2206           */
2207
2208           if(strcmp(s,"W")==0 )
2209             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2210
2211           pic16_emitcode("movwf","%s",
2212                    aop->aopu.aop_reg[offset]->name);
2213
2214           if(strcmp(s,zero)==0) {
2215             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2216
2217           } else if(strcmp(s,"W")==0) {
2218             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2219             pcop->type = PO_GPR_REGISTER;
2220
2221             PCOR(pcop)->rIdx = -1;
2222             PCOR(pcop)->r = NULL;
2223
2224             DEBUGpic16_emitcode(";","%d",__LINE__);
2225             pcop->name = Safe_strdup(s);
2226             pic16_emitpcode(POC_MOVFW,pcop);
2227             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2228           } else if(strcmp(s,one)==0) {
2229             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2230             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2231           } else {
2232             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2233           }
2234         }
2235         break;
2236         
2237     case AOP_DPTR:
2238     case AOP_DPTR2:
2239     
2240     if (aop->type == AOP_DPTR2)
2241     {
2242         genSetDPTR(1);
2243     }
2244     
2245         if (aop->code) {
2246             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2247                    "pic16_aopPut writting to code space");
2248             exit(0);
2249         }
2250         
2251         while (offset > aop->coff) {
2252             aop->coff++;
2253             pic16_emitcode ("inc","dptr");
2254         }
2255         
2256         while (offset < aop->coff) {
2257             aop->coff-- ;
2258             pic16_emitcode("lcall","__decdptr");
2259         }
2260         
2261         aop->coff = offset;
2262         
2263         /* if not in accumulater */
2264         MOVA(s);        
2265         
2266         pic16_emitcode ("movx","@dptr,a");
2267         
2268     if (aop->type == AOP_DPTR2)
2269     {
2270         genSetDPTR(0);
2271     }
2272         break;
2273         
2274     case AOP_R0:
2275     case AOP_R1:
2276         while (offset > aop->coff) {
2277             aop->coff++;
2278             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2279         }
2280         while (offset < aop->coff) {
2281             aop->coff-- ;
2282             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2283         }
2284         aop->coff = offset;
2285         
2286         if (aop->paged) {
2287             MOVA(s);           
2288             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2289             
2290         } else
2291             if (*s == '@') {
2292                 MOVA(s);
2293                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2294             } else
2295                 if (strcmp(s,"r0") == 0 ||
2296                     strcmp(s,"r1") == 0 ||
2297                     strcmp(s,"r2") == 0 ||
2298                     strcmp(s,"r3") == 0 ||
2299                     strcmp(s,"r4") == 0 ||
2300                     strcmp(s,"r5") == 0 ||
2301                     strcmp(s,"r6") == 0 || 
2302                     strcmp(s,"r7") == 0 ) {
2303                     char buffer[10];
2304                     sprintf(buffer,"a%s",s);
2305                     pic16_emitcode("mov","@%s,%s",
2306                              aop->aopu.aop_ptr->name,buffer);
2307                 } else
2308                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2309         
2310         break;
2311         
2312     case AOP_STK:
2313         if (strcmp(s,"a") == 0)
2314             pic16_emitcode("push","acc");
2315         else
2316             pic16_emitcode("push","%s",s);
2317         
2318         break;
2319         
2320     case AOP_CRY:
2321         /* if bit variable */
2322         if (!aop->aopu.aop_dir) {
2323             pic16_emitcode("clr","a");
2324             pic16_emitcode("rlc","a");
2325         } else {
2326             if (s == zero) 
2327                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2328             else
2329                 if (s == one)
2330                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2331                 else
2332                     if (!strcmp(s,"c"))
2333                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2334                     else {
2335                         lbl = newiTempLabel(NULL);
2336                         
2337                         if (strcmp(s,"a")) {
2338                             MOVA(s);
2339                         }
2340                         pic16_emitcode("clr","c");
2341                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2342                         pic16_emitcode("cpl","c");
2343                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2344                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2345                     }
2346         }
2347         break;
2348         
2349     case AOP_STR:
2350         aop->coff = offset;
2351         if (strcmp(aop->aopu.aop_str[offset],s))
2352             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2353         break;
2354         
2355     case AOP_ACC:
2356         aop->coff = offset;
2357         if (!offset && (strcmp(s,"acc") == 0))
2358             break;
2359         
2360         if (strcmp(aop->aopu.aop_str[offset],s))
2361             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2362         break;
2363
2364     default :
2365         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2366 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2367 //             "pic16_aopPut got unsupported aop->type");
2368 //      exit(0);    
2369     }    
2370
2371 }
2372
2373 /*-----------------------------------------------------------------*/
2374 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2375 /*-----------------------------------------------------------------*/
2376 void pic16_mov2w (asmop *aop, int offset)
2377 {
2378   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2379
2380   if(is_LitAOp(aop))
2381     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2382   else
2383     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2384 }
2385
2386 static void mov2f(asmop *dst, asmop *src, int offset)
2387 {
2388   if(is_LitAOp(src)) {
2389     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2390     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2391   } else {
2392     if(pic16_sameRegsOfs(src, dst, offset))return;
2393     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2394                       pic16_popGet(dst, offset)));
2395   }
2396 }
2397
2398 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2399 {
2400   if(is_LitAOp(src)) {
2401     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2402     pic16_emitpcode(POC_MOVWF, dst);
2403   } else {
2404     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2405   }
2406 }
2407
2408 void pic16_testStackOverflow(void)
2409 {
2410 #define GSTACK_TEST_NAME        "_gstack_test"
2411
2412   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2413   
2414   {
2415     symbol *sym;
2416
2417       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2418       sprintf(sym->rname, "%s%s", port->fun_prefix, GSTACK_TEST_NAME);
2419 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2420       checkAddSym(&externs, sym);
2421   }
2422
2423 }
2424
2425 /* push pcop into stack */
2426 void pic16_pushpCodeOp(pCodeOp *pcop)
2427 {
2428 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2429   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));    //&pic16_pc_postdec1)));
2430   if(pic16_options.gstack)
2431     pic16_testStackOverflow();
2432     
2433 }
2434
2435 /* pop pcop from stack */
2436 void pic16_poppCodeOp(pCodeOp *pcop)
2437 {
2438   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2439   if(pic16_options.gstack)
2440     pic16_testStackOverflow();
2441 }
2442
2443
2444 /*-----------------------------------------------------------------*/
2445 /* pushw - pushes wreg to stack                                    */
2446 /*-----------------------------------------------------------------*/
2447 void pushw(void)
2448 {
2449   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2450   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2451   if(pic16_options.gstack)
2452     pic16_testStackOverflow();
2453 }
2454
2455                 
2456 /*-----------------------------------------------------------------*/
2457 /* pushaop - pushes aop to stack                                   */
2458 /*-----------------------------------------------------------------*/
2459 void pushaop(asmop *aop, int offset)
2460 {
2461   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2462
2463   if(is_LitAOp(aop)) {
2464     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2465     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2466   } else {
2467     pic16_emitpcode(POC_MOVFF,
2468       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2469   }
2470
2471   if(pic16_options.gstack)
2472     pic16_testStackOverflow();
2473 }
2474
2475 /*-----------------------------------------------------------------*/
2476 /* popaop - pops aop from stack                                    */
2477 /*-----------------------------------------------------------------*/
2478 void popaop(asmop *aop, int offset)
2479 {
2480   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2481   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2482   if(pic16_options.gstack)
2483     pic16_testStackOverflow();
2484 }
2485
2486 void popaopidx(asmop *aop, int offset, int index)
2487 {
2488   int ofs=1;
2489
2490     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2491
2492     if(STACK_MODEL_LARGE)ofs++;
2493
2494     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2495     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2496     if(pic16_options.gstack)
2497       pic16_testStackOverflow();
2498 }
2499
2500 #if !(USE_GENERIC_SIGNED_SHIFT)
2501 /*-----------------------------------------------------------------*/
2502 /* reAdjustPreg - points a register back to where it should        */
2503 /*-----------------------------------------------------------------*/
2504 static void reAdjustPreg (asmop *aop)
2505 {
2506     int size ;
2507
2508     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2509     aop->coff = 0;
2510     if ((size = aop->size) <= 1)
2511         return ;
2512     size-- ;
2513     switch (aop->type) {
2514         case AOP_R0 :
2515         case AOP_R1 :
2516             while (size--)
2517                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2518             break;          
2519         case AOP_DPTR :
2520         case AOP_DPTR2:
2521             if (aop->type == AOP_DPTR2)
2522             {
2523                 genSetDPTR(1);
2524             } 
2525             while (size--)
2526             {
2527                 pic16_emitcode("lcall","__decdptr");
2528             }
2529                 
2530             if (aop->type == AOP_DPTR2)
2531             {
2532                 genSetDPTR(0);
2533             }                
2534             break;  
2535
2536     }   
2537
2538 }
2539 #endif
2540
2541 #if 0
2542 /*-----------------------------------------------------------------*/
2543 /* opIsGptr: returns non-zero if the passed operand is             */   
2544 /* a generic pointer type.                                         */
2545 /*-----------------------------------------------------------------*/ 
2546 static int opIsGptr(operand *op)
2547 {
2548     sym_link *type = operandType(op);
2549     
2550     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2551     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2552     {
2553         return 1;
2554     }
2555     return 0;        
2556 }
2557 #endif
2558
2559 /*-----------------------------------------------------------------*/
2560 /* pic16_getDataSize - get the operand data size                         */
2561 /*-----------------------------------------------------------------*/
2562 int pic16_getDataSize(operand *op)
2563 {
2564     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2565
2566
2567     return AOP_SIZE(op);
2568
2569     // tsd- in the pic port, the genptr size is 1, so this code here
2570     // fails. ( in the 8051 port, the size was 4).
2571 #if 0
2572     int size;
2573     size = AOP_SIZE(op);
2574     if (size == GPTRSIZE)
2575     {
2576         sym_link *type = operandType(op);
2577         if (IS_GENPTR(type))
2578         {
2579             /* generic pointer; arithmetic operations
2580              * should ignore the high byte (pointer type).
2581              */
2582             size--;
2583     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2584         }
2585     }
2586     return size;
2587 #endif
2588 }
2589
2590 /*-----------------------------------------------------------------*/
2591 /* pic16_outAcc - output Acc                                             */
2592 /*-----------------------------------------------------------------*/
2593 void pic16_outAcc(operand *result)
2594 {
2595   int size,offset;
2596   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2597   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2598
2599
2600   size = pic16_getDataSize(result);
2601   if(size){
2602     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2603     size--;
2604     offset = 1;
2605     /* unsigned or positive */
2606     while(size--)
2607       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2608   }
2609
2610 }
2611
2612 /*-----------------------------------------------------------------*/
2613 /* pic16_outBitC - output a bit C                                  */
2614 /*                 Move to result the value of Carry flag -- VR    */
2615 /*-----------------------------------------------------------------*/
2616 void pic16_outBitC(operand *result)
2617 {
2618   int i;
2619
2620     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2621
2622     /* if the result is bit */
2623     if (AOP_TYPE(result) == AOP_CRY) {
2624         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2625         pic16_aopPut(AOP(result),"c",0);
2626     } else {
2627
2628         i = AOP_SIZE(result);
2629         while(i--) {
2630                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2631         }
2632         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2633     }
2634 }
2635
2636 /*-----------------------------------------------------------------*/
2637 /* pic16_outBitOp - output a bit from Op                           */
2638 /*                 Move to result the value of set/clr op -- VR    */
2639 /*-----------------------------------------------------------------*/
2640 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2641 {
2642   int i;
2643
2644     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2645
2646     /* if the result is bit */
2647     if (AOP_TYPE(result) == AOP_CRY) {
2648         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2649         pic16_aopPut(AOP(result),"c",0);
2650     } else {
2651
2652         i = AOP_SIZE(result);
2653         while(i--) {
2654                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2655         }
2656         pic16_emitpcode(POC_RRCF, pcop);          
2657         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2658     }
2659 }
2660
2661 /*-----------------------------------------------------------------*/
2662 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2663 /*-----------------------------------------------------------------*/
2664 void pic16_toBoolean(operand *oper)
2665 {
2666     int size = AOP_SIZE(oper) - 1;
2667     int offset = 1;
2668
2669     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2670
2671     if ( AOP_TYPE(oper) != AOP_ACC) {
2672       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2673     }
2674     while (size--) {
2675       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2676     }
2677 }
2678
2679
2680 #if !defined(GEN_Not)
2681 /*-----------------------------------------------------------------*/
2682 /* genNot - generate code for ! operation                          */
2683 /*-----------------------------------------------------------------*/
2684 static void pic16_genNot (iCode *ic)
2685 {
2686   symbol *tlbl;
2687   int size;
2688
2689   FENTRY;
2690   /* assign asmOps to operand & result */
2691   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2692   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2693
2694   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2695   /* if in bit space then a special case */
2696   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2697     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2698       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2699       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2700     } else {
2701       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2702       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2703       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2704     }
2705     goto release;
2706   }
2707
2708   size = AOP_SIZE(IC_LEFT(ic));
2709   if(size == 1) {
2710     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2711     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2712     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2713     goto release;
2714   }
2715   pic16_toBoolean(IC_LEFT(ic));
2716
2717   tlbl = newiTempLabel(NULL);
2718   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2719   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2720   pic16_outBitC(IC_RESULT(ic));
2721
2722  release:    
2723   /* release the aops */
2724   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2725   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2726 }
2727 #endif
2728
2729
2730 #if !defined(GEN_Cpl)
2731 /*-----------------------------------------------------------------*/
2732 /* genCpl - generate code for complement                           */
2733 /*-----------------------------------------------------------------*/
2734 static void pic16_genCpl (iCode *ic)
2735 {
2736   int offset = 0;
2737   int size ;
2738
2739     FENTRY;
2740     /* assign asmOps to operand & result */
2741     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2742     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2743
2744     /* if both are in bit space then 
2745     a special case */
2746     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2747         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2748
2749         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2750         pic16_emitcode("cpl","c"); 
2751         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2752         goto release; 
2753     } 
2754
2755     size = AOP_SIZE(IC_RESULT(ic));
2756     while (size--) {
2757 /*
2758         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2759         MOVA(l);       
2760         pic16_emitcode("cpl","a");
2761         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2762 */
2763         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2764               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2765         } else {
2766                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2767                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2768         }
2769         offset++;
2770
2771     }
2772
2773
2774 release:
2775     /* release the aops */
2776     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2777     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2778 }
2779 #endif
2780
2781 /*-----------------------------------------------------------------*/
2782 /* genUminusFloat - unary minus for floating points                */
2783 /*-----------------------------------------------------------------*/
2784 static void genUminusFloat(operand *op,operand *result)
2785 {
2786   int size ,offset =0 ;
2787   
2788     FENTRY;
2789     /* for this we just need to flip the 
2790     first it then copy the rest in place */
2791     size = AOP_SIZE(op);
2792
2793     while(size--) {
2794       mov2f(AOP(result), AOP(op), offset);
2795       offset++;
2796     }
2797     
2798     /* toggle the MSB's highest bit */
2799     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2800 }
2801
2802 /*-----------------------------------------------------------------*/
2803 /* genUminus - unary minus code generation                         */
2804 /*-----------------------------------------------------------------*/
2805 static void genUminus (iCode *ic)
2806 {
2807   int size, i;
2808   sym_link *optype, *rtype;
2809   symbol *label;
2810   int needLabel=0;
2811
2812     FENTRY;     
2813     
2814     /* assign asmops */
2815     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2816     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2817
2818     /* if both in bit space then special case */
2819     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2820       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2821         
2822         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2823         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2824         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2825         goto release; 
2826     } 
2827
2828     optype = operandType(IC_LEFT(ic));
2829     rtype = operandType(IC_RESULT(ic));
2830
2831     /* if float then do float stuff */
2832     if (IS_FLOAT(optype)) {
2833       genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2834       goto release;
2835     }
2836
2837     /* otherwise subtract from zero by taking the 2's complement */
2838     size = AOP_SIZE(IC_LEFT(ic));
2839     label = newiTempLabel ( NULL );
2840     
2841     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2842       for (i=size-1; i > 0; i--) {
2843         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2844       } // for
2845       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2846       for (i=1; i < size; i++) {
2847         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2848         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2849       } // for
2850     } else {
2851       for (i=size-1; i >= 0; i--) {
2852         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2853         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2854       } // for
2855       if (size > 1) {
2856         for (i=0; i < size-2; i++) {
2857           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2858           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2859         } // for
2860         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2861       } // if
2862       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2863     }
2864     if (needLabel)
2865       pic16_emitpLabel (label->key);
2866
2867 release:
2868     /* release the aops */
2869     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2870     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2871 }
2872
2873 #if 0
2874 /*-----------------------------------------------------------------*/
2875 /* saveRegisters - will look for a call and save the registers     */
2876 /*-----------------------------------------------------------------*/
2877 static void saveRegisters(iCode *lic) 
2878 {
2879     int i;
2880     iCode *ic;
2881     bitVect *rsave;
2882     sym_link *dtype;
2883
2884     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2885     /* look for call */
2886     for (ic = lic ; ic ; ic = ic->next) 
2887         if (ic->op == CALL || ic->op == PCALL)
2888             break;
2889
2890     if (!ic) {
2891         fprintf(stderr,"found parameter push with no function call\n");
2892         return ;
2893     }
2894
2895     /* if the registers have been saved already then
2896     do nothing */
2897     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2898         return ;
2899
2900     /* find the registers in use at this time 
2901     and push them away to safety */
2902     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2903                           ic->rUsed);
2904
2905     ic->regsSaved = 1;
2906     if (options.useXstack) {
2907         if (bitVectBitValue(rsave,R0_IDX))
2908             pic16_emitcode("mov","b,r0");
2909         pic16_emitcode("mov","r0,%s",spname);
2910         for (i = 0 ; i < pic16_nRegs ; i++) {
2911             if (bitVectBitValue(rsave,i)) {
2912                 if (i == R0_IDX)
2913                     pic16_emitcode("mov","a,b");
2914                 else
2915                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2916                 pic16_emitcode("movx","@r0,a");
2917                 pic16_emitcode("inc","r0");
2918             }
2919         }
2920         pic16_emitcode("mov","%s,r0",spname);
2921         if (bitVectBitValue(rsave,R0_IDX))
2922             pic16_emitcode("mov","r0,b");           
2923     }// else
2924     //for (i = 0 ; i < pic16_nRegs ; i++) {
2925     //    if (bitVectBitValue(rsave,i))
2926     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2927     //}
2928
2929     dtype = operandType(IC_LEFT(ic));
2930     if (currFunc && dtype && 
2931         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2932         IFFUNC_ISISR(currFunc->type) &&
2933         !ic->bankSaved) 
2934
2935         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2936
2937 }
2938 /*-----------------------------------------------------------------*/
2939 /* unsaveRegisters - pop the pushed registers                      */
2940 /*-----------------------------------------------------------------*/
2941 static void unsaveRegisters (iCode *ic)
2942 {
2943     int i;
2944     bitVect *rsave;
2945
2946     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2947     /* find the registers in use at this time 
2948     and push them away to safety */
2949     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2950                           ic->rUsed);
2951     
2952     if (options.useXstack) {
2953         pic16_emitcode("mov","r0,%s",spname);   
2954         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2955             if (bitVectBitValue(rsave,i)) {
2956                 pic16_emitcode("dec","r0");
2957                 pic16_emitcode("movx","a,@r0");
2958                 if (i == R0_IDX)
2959                     pic16_emitcode("mov","b,a");
2960                 else
2961                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2962             }       
2963
2964         }
2965         pic16_emitcode("mov","%s,r0",spname);
2966         if (bitVectBitValue(rsave,R0_IDX))
2967             pic16_emitcode("mov","r0,b");
2968     } //else
2969     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2970     //    if (bitVectBitValue(rsave,i))
2971     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2972     //}
2973
2974 }  
2975 #endif
2976
2977 #if 0  // patch 14
2978 /*-----------------------------------------------------------------*/
2979 /* pushSide -                                                      */
2980 /*-----------------------------------------------------------------*/
2981 static void pushSide(operand * oper, int size)
2982 {
2983         int offset = 0;
2984     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2985         while (size--) {
2986                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2987                 if (AOP_TYPE(oper) != AOP_REG &&
2988                     AOP_TYPE(oper) != AOP_DIR &&
2989                     strcmp(l,"a") ) {
2990                         pic16_emitcode("mov","a,%s",l);
2991                         pic16_emitcode("push","acc");
2992                 } else
2993                         pic16_emitcode("push","%s",l);
2994         }
2995 }
2996 #endif // patch 14
2997
2998 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2999 {
3000   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3001     pic16_emitpcode(POC_MOVFW, src);
3002     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
3003   } else {
3004     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3005         src, pic16_popGet(AOP(op), offset)));
3006   }
3007 }
3008
3009
3010 /*-----------------------------------------------------------------*/
3011 /* assignResultValue - assign results to oper, rescall==1 is       */
3012 /*                     called from genCall() or genPcall()         */
3013 /*-----------------------------------------------------------------*/
3014 static void assignResultValue(operand * oper, int rescall)
3015 {
3016   int size = AOP_SIZE(oper);
3017   int offset=0;
3018   
3019     FENTRY2;
3020 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3021     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3022
3023     if(rescall) {
3024       /* assign result from a call/pcall function() */
3025                 
3026       /* function results are stored in a special order,
3027        * see top of file with Function return policy, or manual */
3028
3029       if(size <= 4) {
3030         /* 8-bits, result in WREG */
3031         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3032                         
3033         if(size>1) {
3034           /* 16-bits, result in PRODL:WREG */
3035           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3036         }
3037                         
3038         if(size>2) {
3039           /* 24-bits, result in PRODH:PRODL:WREG */
3040           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3041         }
3042                         
3043         if(size>3) {
3044           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3045           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3046         }
3047       
3048       } else {
3049         /* >32-bits, result on stack, and FSR0 points to beginning.
3050          * Fix stack when done */
3051         /* FIXME FIXME */
3052 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3053         while (size--) {
3054 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3055 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3056                 
3057           popaopidx(AOP(oper), size, GpsuedoStkPtr);
3058           GpsuedoStkPtr++;
3059         }
3060                         
3061         /* fix stack */
3062         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3063         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3064         if(STACK_MODEL_LARGE) {
3065           emitSKPNC;
3066           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3067         }
3068       }                 
3069     } else {
3070       int areg = 0;             /* matching argument register */
3071       
3072 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3073       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3074
3075
3076       /* its called from genReceive (probably) -- VR */
3077       /* I hope this code will not be called from somewhere else in the future! 
3078        * We manually set the pseudo stack pointer in genReceive. - dw
3079        */
3080       if(!GpsuedoStkPtr && _G.useWreg) {
3081 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3082
3083         /* The last byte in the assignment is in W */
3084         if(areg <= GpsuedoStkPtr) {
3085           size--;
3086           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3087           offset++;
3088 //          debugf("receive from WREG\n", 0);
3089         }
3090         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3091       }
3092 //      GpsuedoStkPtr++;
3093       _G.stack_lat = AOP_SIZE(oper)-1;
3094
3095       while (size) {
3096         size--;
3097         GpsuedoStkPtr++;
3098         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3099 //        debugf("receive from STACK\n", 0);
3100         offset++;
3101       }
3102     }
3103 }
3104
3105
3106 /*-----------------------------------------------------------------*/
3107 /* genIpush - generate code for pushing this gets a little complex */
3108 /*-----------------------------------------------------------------*/
3109 static void genIpush (iCode *ic)
3110 {
3111 //  int size, offset=0;
3112
3113   FENTRY;
3114   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3115
3116   if(ic->parmPush) {
3117     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3118
3119     /* send to stack as normal */
3120     addSet(&_G.sendSet,ic);
3121 //    addSetHead(&_G.sendSet,ic);
3122     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3123   }
3124
3125         
3126 #if 0
3127     int size, offset = 0 ;
3128     char *l;
3129
3130
3131     /* if this is not a parm push : ie. it is spill push 
3132     and spill push is always done on the local stack */
3133     if (!ic->parmPush) {
3134
3135         /* and the item is spilt then do nothing */
3136         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3137             return ;
3138
3139         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3140         size = AOP_SIZE(IC_LEFT(ic));
3141         /* push it on the stack */
3142         while(size--) {
3143             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3144             if (*l == '#') {
3145                 MOVA(l);
3146                 l = "acc";
3147             }
3148             pic16_emitcode("push","%s",l);
3149         }
3150         return ;        
3151     }
3152
3153     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3154 #endif
3155 }
3156
3157 /*-----------------------------------------------------------------*/
3158 /* genIpop - recover the registers: can happen only for spilling   */
3159 /*-----------------------------------------------------------------*/
3160 static void genIpop (iCode *ic)
3161 {
3162   FENTRY;
3163   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3164 #if 0
3165     int size,offset ;
3166
3167
3168     /* if the temp was not pushed then */
3169     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3170         return ;
3171
3172     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3173     size = AOP_SIZE(IC_LEFT(ic));
3174     offset = (size-1);
3175     while (size--) 
3176         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3177                                    FALSE,TRUE));
3178
3179     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3180 #endif
3181 }
3182
3183 #if 0
3184 /*-----------------------------------------------------------------*/
3185 /* unsaverbank - restores the resgister bank from stack            */
3186 /*-----------------------------------------------------------------*/
3187 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3188 {
3189   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3190 #if 0
3191     int i;
3192     asmop *aop ;
3193     regs *r = NULL;
3194
3195     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3196     if (popPsw) {
3197         if (options.useXstack) {
3198             aop = newAsmop(0);
3199             r = getFreePtr(ic,&aop,FALSE);
3200             
3201             
3202             pic16_emitcode("mov","%s,_spx",r->name);
3203             pic16_emitcode("movx","a,@%s",r->name);
3204             pic16_emitcode("mov","psw,a");
3205             pic16_emitcode("dec","%s",r->name);
3206             
3207         }else
3208             pic16_emitcode ("pop","psw");
3209     }
3210
3211     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3212         if (options.useXstack) {       
3213             pic16_emitcode("movx","a,@%s",r->name);
3214             //pic16_emitcode("mov","(%s+%d),a",
3215             //       regspic16[i].base,8*bank+regspic16[i].offset);
3216             pic16_emitcode("dec","%s",r->name);
3217
3218         } else 
3219           pic16_emitcode("pop",""); //"(%s+%d)",
3220         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3221     }
3222
3223     if (options.useXstack) {
3224
3225         pic16_emitcode("mov","_spx,%s",r->name);
3226         pic16_freeAsmop(NULL,aop,ic,TRUE);
3227
3228     }
3229 #endif 
3230 }
3231
3232 /*-----------------------------------------------------------------*/
3233 /* saverbank - saves an entire register bank on the stack          */
3234 /*-----------------------------------------------------------------*/
3235 static void saverbank (int bank, iCode *ic, bool pushPsw)
3236 {
3237   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3238 #if 0
3239     int i;
3240     asmop *aop ;
3241     regs *r = NULL;
3242
3243     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3244     if (options.useXstack) {
3245
3246         aop = newAsmop(0);
3247         r = getFreePtr(ic,&aop,FALSE);  
3248         pic16_emitcode("mov","%s,_spx",r->name);
3249
3250     }
3251
3252     for (i = 0 ; i < pic16_nRegs ;i++) {
3253         if (options.useXstack) {
3254             pic16_emitcode("inc","%s",r->name);
3255             //pic16_emitcode("mov","a,(%s+%d)",
3256             //         regspic16[i].base,8*bank+regspic16[i].offset);
3257             pic16_emitcode("movx","@%s,a",r->name);           
3258         } else 
3259           pic16_emitcode("push","");// "(%s+%d)",
3260                      //regspic16[i].base,8*bank+regspic16[i].offset);
3261     }
3262     
3263     if (pushPsw) {
3264         if (options.useXstack) {
3265             pic16_emitcode("mov","a,psw");
3266             pic16_emitcode("movx","@%s,a",r->name);     
3267             pic16_emitcode("inc","%s",r->name);
3268             pic16_emitcode("mov","_spx,%s",r->name);       
3269             pic16_freeAsmop (NULL,aop,ic,TRUE);
3270             
3271         } else
3272             pic16_emitcode("push","psw");
3273         
3274         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3275     }
3276     ic->bankSaved = 1;
3277 #endif
3278 }
3279 #endif  /* 0 */
3280
3281
3282 static int wparamCmp(void *p1, void *p2)
3283 {
3284   return (!strcmp((char *)p1, (char *)p2));
3285 }
3286
3287 int inWparamList(char *s)
3288 {
3289   return isinSetWith(wparamList, s, wparamCmp);
3290
3291
3292
3293 /*-----------------------------------------------------------------*/
3294 /* genCall - generates a call statement                            */
3295 /*-----------------------------------------------------------------*/
3296 static void genCall (iCode *ic)
3297 {
3298   sym_link *ftype;   
3299   int stackParms=0;
3300   int use_wreg=0;
3301   int inwparam=0;
3302   char *fname;
3303   
3304     FENTRY;
3305
3306     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3307     /* if caller saves & we have not saved then */
3308 //    if (!ic->regsSaved)
3309 //      saveRegisters(ic);
3310
3311         /* initialise stackParms for IPUSH pushes */
3312 //      stackParms = psuedoStkPtr;
3313 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3314     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3315     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3316
3317 #if 0
3318     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3319 #endif
3320
3321     /* if send set is not empty the assign */
3322     if (_G.sendSet) {
3323       iCode *sic;
3324       int psuedoStkPtr=-1; 
3325       int firstTimeThruLoop = 1;
3326
3327
3328         /* reverse sendSet if function is not reentrant */
3329         if(!IFFUNC_ISREENT(ftype))
3330           _G.sendSet = reverseSet(_G.sendSet);
3331
3332         /* First figure how many parameters are getting passed */
3333         stackParms = 0;
3334         use_wreg = 0;
3335         
3336         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3337           int size;
3338 //          int offset = 0;
3339
3340             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3341             size = AOP_SIZE(IC_LEFT(sic));
3342
3343             stackParms += size;
3344
3345             /* pass the last byte through WREG */
3346             if(inwparam) {
3347
3348               while (size--) {
3349                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3350                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3351                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3352
3353                 if(!firstTimeThruLoop) {
3354                   /* If this is not the first time we've been through the loop
3355                    * then we need to save the parameter in a temporary
3356                    * register. The last byte of the last parameter is
3357                    * passed in W. */
3358
3359                   pushw();
3360 //                  --psuedoStkPtr;             // sanity check
3361                   use_wreg = 1;
3362                 }
3363                 
3364                 firstTimeThruLoop=0;
3365
3366                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3367
3368 //                offset++;
3369               }
3370             } else {
3371               /* all arguments are passed via stack */
3372               use_wreg = 0;
3373
3374               while (size--) {
3375                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3376                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3377                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3378
3379 //                pushaop(AOP(IC_LEFT(sic)), size);
3380                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3381
3382                 if(!_G.resDirect)
3383                   pushw();
3384               }
3385             }
3386
3387             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3388           }
3389
3390           if(inwparam) {
3391             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3392               pushw();  /* save last parameter to stack if functions has varargs */
3393               use_wreg = 0;
3394             } else
3395               use_wreg = 1;
3396           } else use_wreg = 0;
3397
3398           _G.stackRegSet = _G.sendSet;
3399           _G.sendSet = NULL;
3400     }
3401
3402     /* make the call */
3403     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3404
3405     GpsuedoStkPtr=0;
3406     
3407     /* if we need to assign a result value */
3408     if ((IS_ITEMP(IC_RESULT(ic))
3409           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3410               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3411         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3412
3413       _G.accInUse++;
3414       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3415       _G.accInUse--;
3416
3417       assignResultValue(IC_RESULT(ic), 1);
3418
3419       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3420                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3421                 
3422       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3423     }
3424
3425     if(!stackParms && ic->parmBytes) {
3426       stackParms = ic->parmBytes;
3427     }
3428       
3429     stackParms -= use_wreg;
3430     
3431     if(stackParms>0) {
3432       if(stackParms == 1) {
3433         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3434       } else {
3435         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3436         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3437       }
3438       if(STACK_MODEL_LARGE) {
3439         emitSKPNC;
3440         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3441       }
3442     }
3443
3444 #if 0
3445     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3446 #endif
3447
3448     /* adjust the stack for parameters if required */
3449 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3450
3451 #if 0
3452       /* if register bank was saved then pop them */
3453       if (ic->bankSaved)
3454         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3455
3456       /* if we hade saved some registers then unsave them */
3457       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3458         unsaveRegisters (ic);
3459 #endif
3460 }
3461
3462
3463
3464 /*-----------------------------------------------------------------*/
3465 /* genPcall - generates a call by pointer statement                */
3466 /*            new version, created from genCall - HJD              */
3467 /*-----------------------------------------------------------------*/
3468 static void genPcall (iCode *ic)
3469 {
3470   sym_link *ftype, *fntype;
3471   int stackParms=0;
3472   symbol *retlbl = newiTempLabel(NULL);
3473   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3474   
3475     FENTRY;
3476
3477     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3478     fntype = operandType( IC_LEFT(ic) )->next;
3479
3480     /* if send set is not empty the assign */
3481     if (_G.sendSet) {
3482       iCode *sic;
3483       int psuedoStkPtr=-1; 
3484
3485       /* reverse sendSet if function is not reentrant */
3486       if(!IFFUNC_ISREENT(fntype))
3487         _G.sendSet = reverseSet(_G.sendSet);
3488
3489       stackParms = 0;
3490       
3491       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3492         int size;
3493
3494           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3495           size = AOP_SIZE(IC_LEFT(sic));
3496           stackParms += size;
3497
3498           /* all parameters are passed via stack, since WREG is clobbered
3499            * by the calling sequence */
3500           while (size--) {
3501             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3502             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3503             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3504
3505             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3506             pushw();
3507           }
3508
3509           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3510       }
3511
3512       _G.stackRegSet = _G.sendSet;
3513       _G.sendSet = NULL;
3514     }
3515
3516     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3517
3518     // push return address
3519     // push $ on return stack, then replace with retlbl
3520
3521     /* Thanks to Thorsten Klose for pointing out that the following
3522      * snippet should be interrupt safe */
3523     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3524     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3525
3526     pic16_emitpcodeNULLop(POC_PUSH);
3527
3528     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3529     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3530     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3531     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3532     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3533     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3534
3535
3536     /* restore interrupt control register */
3537     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3538     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3539
3540     /* make the call by writing the pointer into pc */
3541     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3542     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3543
3544     // note: MOVFF to PCL not allowed
3545     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3546     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3547
3548
3549     /* return address is here: (X) */
3550     pic16_emitpLabelFORCE(retlbl->key);
3551
3552     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3553
3554     GpsuedoStkPtr=0;
3555     /* if we need assign a result value */
3556     if ((IS_ITEMP(IC_RESULT(ic))
3557           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3558               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3559         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3560
3561       _G.accInUse++;
3562       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3563       _G.accInUse--;
3564
3565       assignResultValue(IC_RESULT(ic), 1);
3566
3567       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3568               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3569                 
3570       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3571     }
3572
3573 //    stackParms -= use_wreg;
3574     
3575     if(stackParms>0) {
3576       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3577       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3578       if(STACK_MODEL_LARGE) {
3579         emitSKPNC;
3580         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3581       }
3582     }
3583 }
3584
3585 /*-----------------------------------------------------------------*/
3586 /* resultRemat - result  is rematerializable                       */
3587 /*-----------------------------------------------------------------*/
3588 static int resultRemat (iCode *ic)
3589 {
3590   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3591   if (SKIP_IC(ic) || ic->op == IFX)
3592     return 0;
3593
3594   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3595     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3596     if (sym->remat && !POINTER_SET(ic)) 
3597       return 1;
3598   }
3599
3600   return 0;
3601 }
3602
3603 #if defined(__BORLANDC__) || defined(_MSC_VER)
3604 #define STRCASECMP stricmp
3605 #else
3606 #define STRCASECMP strcasecmp
3607 #endif
3608
3609 #if 0
3610 /*-----------------------------------------------------------------*/
3611 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3612 /*-----------------------------------------------------------------*/
3613 static bool inExcludeList(char *s)
3614 {
3615   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3616     int i =0;
3617     
3618     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3619     if (options.excludeRegs[i] &&
3620     STRCASECMP(options.excludeRegs[i],"none") == 0)
3621         return FALSE ;
3622
3623     for ( i = 0 ; options.excludeRegs[i]; i++) {
3624         if (options.excludeRegs[i] &&
3625         STRCASECMP(s,options.excludeRegs[i]) == 0)
3626             return TRUE;
3627     }
3628     return FALSE ;
3629 }
3630 #endif
3631
3632 /*-----------------------------------------------------------------*/
3633 /* genFunction - generated code for function entry                 */
3634 /*-----------------------------------------------------------------*/
3635 static void genFunction (iCode *ic)
3636 {
3637   symbol *sym;
3638   sym_link *ftype;
3639   
3640     FENTRY;
3641     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3642
3643     pic16_labelOffset += (max_key+4);
3644     max_key=0;
3645     GpsuedoStkPtr=0;
3646     _G.nRegsSaved = 0;
3647         
3648     ftype = operandType(IC_LEFT(ic));
3649     sym = OP_SYMBOL(IC_LEFT(ic));
3650
3651     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3652       /* create an absolute section at the interrupt vector:
3653        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3654       symbol *asym;
3655       char asymname[128];
3656       pBlock *apb;
3657
3658 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3659
3660         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3661           sprintf(asymname, "ivec_%s", sym->name);
3662         else
3663           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3664   
3665         /* when an interrupt is declared as naked, do not emit the special
3666          * wrapper segment at vector address. The user should take care for
3667          * this instead. -- VR */
3668
3669         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3670           asym = newSymbol(asymname, 0);
3671           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3672           pic16_addpBlock( apb );
3673
3674           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3675           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3676           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3677           pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3678                 
3679           /* mark the end of this tiny function */
3680           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3681         } else {
3682           sprintf(asymname, "%s", sym->rname);
3683         }
3684
3685         {
3686           absSym *abSym;
3687
3688             abSym = Safe_calloc(1, sizeof(absSym));
3689             strcpy(abSym->name, asymname);
3690
3691             switch( FUNC_INTNO(sym->type) ) {
3692               case 0: abSym->address = 0x000000; break;
3693               case 1: abSym->address = 0x000008; break;
3694               case 2: abSym->address = 0x000018; break;
3695               
3696               default:
3697 //                fprintf(stderr, "no interrupt number is given\n");
3698                 abSym->address = -1; break;
3699             }
3700
3701             /* relocate interrupt vectors if needed */
3702             if(abSym->address != -1)
3703               abSym->address += pic16_options.ivt_loc;
3704
3705             addSet(&absSymSet, abSym);
3706         }
3707     }
3708
3709     /* create the function header */
3710     pic16_emitcode(";","-----------------------------------------");
3711     pic16_emitcode(";"," function %s",sym->name);
3712     pic16_emitcode(";","-----------------------------------------");
3713
3714     pic16_emitcode("","%s:",sym->rname);
3715     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3716
3717     {
3718       absSym *ab;
3719
3720         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3721           if(!strcmp(ab->name, sym->rname)) {
3722             pic16_pBlockConvert2Absolute(pb);
3723             break;
3724           }
3725         }
3726     }
3727
3728     if(IFFUNC_ISNAKED(ftype)) {
3729       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3730       return;
3731     }
3732         
3733     /* if critical function then turn interrupts off */
3734     if (IFFUNC_ISCRITICAL(ftype)) {
3735       //pic16_emitcode("clr","ea");
3736     }
3737
3738     currFunc = sym;             /* update the currFunc symbol */
3739     _G.fregsUsed = sym->regsUsed;
3740     _G.sregsAlloc = newBitVect(128);
3741     
3742
3743     /* if this is an interrupt service routine then
3744      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3745     if (IFFUNC_ISISR(sym->type)) {
3746         _G.usefastretfie = 1;   /* use shadow registers by default */
3747         
3748         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3749         if(!FUNC_ISSHADOWREGS(sym->type)) {
3750           /* do not save WREG,STATUS,BSR for high priority interrupts
3751            * because they are stored in the hardware shadow registers already */
3752           _G.usefastretfie = 0;
3753           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3754           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3755           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3756         }
3757
3758         /* these should really be optimized somehow, because not all
3759          * interrupt handlers modify them */
3760         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3761         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3762         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3763         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3764         
3765 //        pic16_pBlockConvert2ISR(pb);
3766     }
3767
3768     /* emit code to setup stack frame if user enabled,
3769      * and function is not main() */
3770     
3771 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3772     if(strcmp(sym->name, "main")) {
3773       if(0 
3774         || !options.ommitFramePtr 
3775 //        || sym->regsUsed
3776         || IFFUNC_ARGS(sym->type)
3777         || FUNC_HASSTACKPARM(sym->etype)
3778         ) {
3779         /* setup the stack frame */
3780         if(STACK_MODEL_LARGE)
3781           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3782         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3783
3784         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3785         if(STACK_MODEL_LARGE)
3786           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3787       }
3788     }
3789
3790     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3791           && sym->stack) {
3792
3793       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3794
3795       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3796       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3797       emitSKPC;
3798       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3799     }
3800           
3801     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3802       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3803         _G.useWreg = 0;
3804       else
3805         _G.useWreg = 1;
3806     } else
3807       _G.useWreg = 0;
3808
3809     /* if callee-save to be used for this function
3810      * then save the registers being used in this function */
3811 //    if (IFFUNC_CALLEESAVES(sym->type))
3812     {
3813       int i;
3814
3815         /* if any registers used */
3816         if (sym->regsUsed) {
3817           /* save the registers used */
3818           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3819           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3820           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3821             if (bitVectBitValue(sym->regsUsed,i)) {
3822               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3823               _G.nRegsSaved++;
3824
3825               if(!pic16_regWithIdx(i)->wasUsed) {
3826                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3827                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3828                 pic16_regWithIdx(i)->wasUsed = 1;
3829               }
3830             }
3831           }
3832           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3833         }
3834     }
3835         
3836     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3837 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3838 }
3839
3840 /*-----------------------------------------------------------------*/
3841 /* genEndFunction - generates epilogue for functions               */
3842 /*-----------------------------------------------------------------*/
3843 static void genEndFunction (iCode *ic)
3844 {
3845   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3846
3847     FENTRY;
3848
3849     if(IFFUNC_ISNAKED(sym->type)) {
3850       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3851       return;
3852     }
3853
3854     _G.stack_lat = 0;
3855
3856     /* add code for ISCRITICAL */
3857     if(IFFUNC_ISCRITICAL(sym->type)) {
3858       /* if critical function, turn on interrupts */
3859       
3860       /* TODO: add code here -- VR */
3861     }
3862     
3863 //    sym->regsUsed = _G.fregsUsed;
3864     
3865     /* now we need to restore the registers */
3866     /* if any registers used */
3867
3868     /* first restore registers that might be used for stack access */
3869     if(_G.sregsAllocSet) {
3870     regs *sr;
3871     
3872       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3873       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3874         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3875       }
3876     }
3877
3878     if (sym->regsUsed) {
3879       int i;
3880
3881         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3882         /* restore registers used */
3883         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3884         for ( i = sym->regsUsed->size; i >= 0; i--) {
3885           if (bitVectBitValue(sym->regsUsed,i)) {
3886             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3887             _G.nRegsSaved--;
3888           }
3889         }
3890         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3891     }
3892
3893       
3894
3895     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3896           && sym->stack) {
3897       if (sym->stack == 1) {
3898         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3899         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3900       } else {
3901         // we have to add more than one...
3902         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3903         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3904         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3905         emitSKPNC;
3906         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3907         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3908         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3909       }
3910     }
3911
3912     if(strcmp(sym->name, "main")) {
3913       if(0
3914         || !options.ommitFramePtr
3915 //        || sym->regsUsed
3916         || IFFUNC_ARGS(sym->type)
3917         || FUNC_HASSTACKPARM(sym->etype)
3918         ) {
3919         /* restore stack frame */
3920         if(STACK_MODEL_LARGE)
3921           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3922         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3923       }
3924     }
3925
3926     _G.useWreg = 0;
3927
3928     if (IFFUNC_ISISR(sym->type)) {
3929       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3930       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3931       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3932       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3933
3934       if(!FUNC_ISSHADOWREGS(sym->type)) {
3935         /* do not restore interrupt vector for WREG,STATUS,BSR
3936          * for high priority interrupt, see genFunction */
3937         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3938         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3939         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3940       }
3941 //      _G.interruptvector = 0;         /* sanity check */
3942
3943
3944       /* if debug then send end of function */
3945 /*      if (options.debug && currFunc)  */
3946       if (currFunc) {
3947         debugFile->writeEndFunction (currFunc, ic, 1);
3948       }
3949         
3950       if(_G.usefastretfie)
3951         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3952       else
3953         pic16_emitpcodeNULLop(POC_RETFIE);
3954
3955       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3956       
3957       _G.usefastretfie = 0;
3958       return;
3959     }
3960
3961     if (IFFUNC_ISCRITICAL(sym->type)) {
3962       pic16_emitcode("setb","ea");
3963     }
3964
3965     /* if debug then send end of function */
3966     if (currFunc) {
3967       debugFile->writeEndFunction (currFunc, ic, 1);
3968     }
3969
3970     /* insert code to restore stack frame, if user enabled it
3971      * and function is not main() */
3972          
3973
3974     pic16_emitpcodeNULLop(POC_RETURN);
3975
3976     /* Mark the end of a function */
3977     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3978 }
3979
3980
3981 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3982 {
3983   unsigned long lit=1;
3984   operand *op;
3985
3986     op = IC_LEFT(ic);
3987   
3988     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3989     if(AOP_TYPE(op) == AOP_LIT) {
3990       if(!IS_FLOAT(operandType( op ))) {
3991         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3992       } else {
3993         union {
3994           unsigned long lit_int;
3995           float lit_float;
3996         } info;
3997         
3998         /* take care if literal is a float */
3999         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4000         lit = info.lit_int;
4001       }
4002     }
4003
4004     if(is_LitOp(op)) {
4005       if(/*(OP_LIVETO(op) <= ic->seq) &&*/ (lit == 0)) {
4006         pic16_emitpcode(POC_CLRF, dest);
4007       } else {
4008         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
4009         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
4010       }
4011     } else {
4012       if(dest->type == PO_WREG && (offset == 0)) {
4013         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4014       return;
4015     }
4016     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4017   }
4018 }
4019
4020 /*-----------------------------------------------------------------*/
4021 /* genRet - generate code for return statement                     */
4022 /*-----------------------------------------------------------------*/
4023 static void genRet (iCode *ic)
4024 {
4025   int size;
4026   operand *left;
4027
4028     FENTRY;
4029         /* if we have no return value then
4030          * just generate the "ret" */
4031         
4032         if (!IC_LEFT(ic)) 
4033                 goto jumpret;       
4034     
4035         /* we have something to return then
4036          * move the return value into place */
4037         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4038         size = AOP_SIZE(IC_LEFT(ic));
4039
4040         if(size <= 4) {
4041           if(size>3)
4042             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4043           
4044           if(size>2)
4045             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4046
4047           if(size>1)
4048             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4049           
4050           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4051
4052         } else {
4053                 /* >32-bits, setup stack and FSR0 */
4054                 while (size--) {
4055 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4056 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4057
4058                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4059
4060 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
4061                         GpsuedoStkPtr++;
4062                 }
4063                         
4064                 /* setup FSR0 */
4065                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4066                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4067
4068                 if(STACK_MODEL_LARGE) {
4069                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4070                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4071                 } else {
4072                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4073                 }
4074         }
4075                                 
4076 #if 0
4077         /* old code, left here for reference -- VR */    
4078         while (size--) {
4079           char *l ;
4080
4081                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4082                         /* #NOCHANGE */
4083                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4084                         pic16_emitpcomment("push %s",l);
4085                         pushed++;
4086                 } else {
4087                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4088                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4089                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4090                         
4091                         if (strcmp(fReturn[offset],l)) {
4092                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4093                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4094                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4095                                 } else {
4096                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4097                                 }
4098                                 
4099                                 if(size) {
4100                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4101                                 }
4102                                 offset++;
4103                         }
4104                 }
4105         }    
4106
4107         if (pushed) {
4108                 while(pushed) {
4109                         pushed--;
4110                         if (strcmp(fReturn[pushed],"a"))
4111                                 pic16_emitcode("pop",fReturn[pushed]);
4112                         else
4113                                 pic16_emitcode("pop","acc");
4114                 }
4115         }
4116 #endif
4117
4118
4119         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4120     
4121 jumpret:
4122         /* generate a jump to the return label
4123          * if the next is not the return statement */
4124         if (!(ic->next && ic->next->op == LABEL
4125                 && IC_LABEL(ic->next) == returnLabel)) {
4126         
4127                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4128                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4129         }
4130 }
4131
4132 /*-----------------------------------------------------------------*/
4133 /* genLabel - generates a label                                    */
4134 /*-----------------------------------------------------------------*/
4135 static void genLabel (iCode *ic)
4136 {
4137   FENTRY;
4138
4139   /* special case never generate */
4140   if (IC_LABEL(ic) == entryLabel)
4141     return ;
4142
4143   pic16_emitpLabel(IC_LABEL(ic)->key);
4144 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4145 }
4146
4147 /*-----------------------------------------------------------------*/
4148 /* genGoto - generates a goto                                      */
4149 /*-----------------------------------------------------------------*/
4150 //tsd
4151 static void genGoto (iCode *ic)
4152 {
4153   FENTRY;
4154   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4155 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4156 }
4157
4158
4159 /*-----------------------------------------------------------------*/
4160 /* genMultbits :- multiplication of bits                           */
4161 /*-----------------------------------------------------------------*/
4162 static void genMultbits (operand *left, 
4163                          operand *right, 
4164                          operand *result)
4165 {
4166   FENTRY;
4167
4168   if(!pic16_sameRegs(AOP(result),AOP(right)))
4169     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4170
4171   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4172   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4173   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4174
4175 }
4176
4177
4178 /*-----------------------------------------------------------------*/
4179 /* genMultOneByte : 8 bit multiplication & division                */
4180 /*-----------------------------------------------------------------*/
4181 static void genMultOneByte (operand *left,
4182                             operand *right,
4183                             operand *result)
4184 {
4185
4186   FENTRY;
4187   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4188   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4189
4190   /* (if two literals, the value is computed before) */
4191   /* if one literal, literal on the right */
4192   if (AOP_TYPE(left) == AOP_LIT){
4193     operand *t = right;
4194     right = left;
4195     left = t;
4196   }
4197
4198         /* size is already checked in genMult == 1 */
4199 //      size = AOP_SIZE(result);
4200
4201         if (AOP_TYPE(right) == AOP_LIT){
4202                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4203                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4204                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4205                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4206         } else {
4207                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4208                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4209                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4210                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4211         }
4212         
4213         pic16_genMult8X8_8 (left, right,result);
4214 }
4215
4216 /*-----------------------------------------------------------------*/
4217 /* genMultOneWord : 16 bit multiplication                          */
4218 /*-----------------------------------------------------------------*/
4219 static void genMultOneWord (operand *left,
4220                             operand *right,
4221                             operand *result)
4222 {
4223   FENTRY;
4224   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4225   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4226
4227   /* (if two literals, the value is computed before)
4228    * if one literal, literal on the right */
4229   if (AOP_TYPE(left) == AOP_LIT){
4230     operand *t = right;
4231     right = left;
4232     left = t;
4233   }
4234
4235   /* size is checked already == 2 */
4236 //  size = AOP_SIZE(result);
4237
4238   if (AOP_TYPE(right) == AOP_LIT) {
4239     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4240       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4241       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4242       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4243   } else {
4244     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4245       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4246       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4247       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4248   }
4249         
4250   pic16_genMult16X16_16(left, right,result);
4251 }
4252
4253 /*-----------------------------------------------------------------*/
4254 /* genMultOneLong : 32 bit multiplication                          */
4255 /*-----------------------------------------------------------------*/
4256 static void genMultOneLong (operand *left,
4257                             operand *right,
4258                             operand *result)
4259 {
4260   FENTRY;
4261   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4262   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4263
4264   /* (if two literals, the value is computed before)
4265    * if one literal, literal on the right */
4266   if (AOP_TYPE(left) == AOP_LIT){
4267     operand *t = right;
4268     right = left;
4269     left = t;
4270   }
4271
4272   /* size is checked already == 4 */
4273 //  size = AOP_SIZE(result);
4274
4275   if (AOP_TYPE(right) == AOP_LIT) {
4276     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4277         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4278         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4279         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4280   } else {
4281     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4282         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4283         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4284         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4285   }
4286         
4287   pic16_genMult32X32_32(left, right,result);
4288 }
4289
4290
4291
4292 /*-----------------------------------------------------------------*/
4293 /* genMult - generates code for multiplication                     */
4294 /*-----------------------------------------------------------------*/
4295 static void genMult (iCode *ic)
4296 {
4297   operand *left = IC_LEFT(ic);
4298   operand *right = IC_RIGHT(ic);
4299   operand *result= IC_RESULT(ic);   
4300
4301     FENTRY;
4302         /* assign the amsops */
4303         pic16_aopOp (left,ic,FALSE);
4304         pic16_aopOp (right,ic,FALSE);
4305         pic16_aopOp (result,ic,TRUE);
4306
4307         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4308
4309         /* special cases first *
4310         * both are bits */
4311         if (AOP_TYPE(left) == AOP_CRY
4312                 && AOP_TYPE(right)== AOP_CRY) {
4313                 genMultbits(left,right,result);
4314           goto release ;
4315         }
4316
4317         /* if both are of size == 1 */
4318         if(AOP_SIZE(left) == 1
4319                 && AOP_SIZE(right) == 1) {
4320                 genMultOneByte(left,right,result);
4321           goto release ;
4322         }
4323
4324         /* if both are of size == 2 */
4325         if(AOP_SIZE(left) == 2
4326                 && AOP_SIZE(right) == 2) {
4327                 genMultOneWord(left, right, result);
4328           goto release;
4329         }
4330         
4331         /* if both are of size == 4 */
4332         if(AOP_SIZE(left) == 4
4333                 && AOP_SIZE(right) == 4) {
4334                 genMultOneLong(left, right, result);
4335           goto release;
4336         }
4337         
4338         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4339
4340
4341         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4342         /* should have been converted to function call */
4343         assert(0) ;
4344
4345 release :
4346         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4347         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4348         pic16_freeAsmop(result,NULL,ic,TRUE); 
4349 }
4350
4351 /*-----------------------------------------------------------------*/
4352 /* genDivbits :- division of bits                                  */
4353 /*-----------------------------------------------------------------*/
4354 static void genDivbits (operand *left, 
4355                         operand *right, 
4356                         operand *result)
4357 {
4358   char *l;
4359
4360     FENTRY;
4361     /* the result must be bit */    
4362     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4363     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4364
4365     MOVA(l);    
4366
4367     pic16_emitcode("div","ab");
4368     pic16_emitcode("rrc","a");
4369     pic16_aopPut(AOP(result),"c",0);
4370 }
4371
4372 /*-----------------------------------------------------------------*/
4373 /* genDivOneByte : 8 bit division                                  */
4374 /*-----------------------------------------------------------------*/
4375 static void genDivOneByte (operand *left,
4376                            operand *right,
4377                            operand *result)
4378 {
4379   sym_link *opetype = operandType(result);
4380   char *l ;
4381   symbol *lbl ;
4382   int size,offset;
4383
4384         /* result = divident / divisor
4385          * - divident may be a register or a literal,
4386          * - divisor may be a register or a literal,
4387          * so there are 3 cases (literal / literal is optimized
4388          * by the front-end) to handle.
4389          * In addition we must handle signed and unsigned, which
4390          * result in 6 final different cases -- VR */
4391
4392     FENTRY;
4393     
4394     size = AOP_SIZE(result) - 1;
4395     offset = 1;
4396     /* signed or unsigned */
4397     if (SPEC_USIGN(opetype)) {
4398       pCodeOp *pct1,    /* count */
4399                 *pct2,  /* reste */
4400                 *pct3;  /* temp */
4401       symbol *label1, *label2, *label3;;
4402
4403
4404         /* unsigned is easy */
4405
4406         pct1 = pic16_popGetTempReg(1);
4407         pct2 = pic16_popGetTempReg(1);
4408         pct3 = pic16_popGetTempReg(1);
4409         
4410         label1 = newiTempLabel(NULL);
4411         label2 = newiTempLabel(NULL);
4412         label3 = newiTempLabel(NULL);
4413
4414         /* the following algorithm is extracted from divuint.c */
4415
4416         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4417         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4418         
4419         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4420
4421         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4422         
4423         pic16_emitpLabel(label1->key);
4424         
4425         emitCLRC;
4426         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4427
4428
4429         emitCLRC;
4430         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4431         
4432
4433         emitSKPNC;
4434         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4435         
4436         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4437         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4438         
4439         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4440         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4441         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4442         
4443         pic16_emitpLabel( label3->key );
4444         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4445         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4446         
4447         
4448
4449         pic16_emitpLabel(label2->key);
4450         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4451         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4452         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4453         
4454         /* result is in wreg */
4455         if(AOP_TYPE(result) != AOP_ACC)
4456                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4457
4458         pic16_popReleaseTempReg( pct3, 1);
4459         pic16_popReleaseTempReg( pct2, 1);
4460         pic16_popReleaseTempReg( pct1, 1);
4461
4462         return ;
4463     }
4464
4465     /* signed is a little bit more difficult */
4466
4467     /* save the signs of the operands */
4468     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4469     MOVA(l);    
4470     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4471     pic16_emitcode("push","acc"); /* save it on the stack */
4472
4473     /* now sign adjust for both left & right */
4474     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4475     MOVA(l);       
4476     lbl = newiTempLabel(NULL);
4477     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4478     pic16_emitcode("cpl","a");   
4479     pic16_emitcode("inc","a");
4480     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4481     pic16_emitcode("mov","b,a");
4482
4483     /* sign adjust left side */
4484     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4485     MOVA(l);
4486
4487     lbl = newiTempLabel(NULL);
4488     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4489     pic16_emitcode("cpl","a");
4490     pic16_emitcode("inc","a");
4491     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4492
4493     /* now the division */
4494     pic16_emitcode("div","ab");
4495     /* we are interested in the lower order
4496     only */
4497     pic16_emitcode("mov","b,a");
4498     lbl = newiTempLabel(NULL);
4499     pic16_emitcode("pop","acc");   
4500     /* if there was an over flow we don't 
4501     adjust the sign of the result */
4502     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4503     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4504     CLRC;
4505     pic16_emitcode("clr","a");
4506     pic16_emitcode("subb","a,b");
4507     pic16_emitcode("mov","b,a");
4508     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4509
4510     /* now we are done */
4511     pic16_aopPut(AOP(result),"b",0);
4512     if(size > 0){
4513         pic16_emitcode("mov","c,b.7");
4514         pic16_emitcode("subb","a,acc");   
4515     }
4516     while (size--)
4517         pic16_aopPut(AOP(result),"a",offset++);
4518
4519 }
4520
4521 /*-----------------------------------------------------------------*/
4522 /* genDiv - generates code for division                            */
4523 /*-----------------------------------------------------------------*/
4524 static void genDiv (iCode *ic)
4525 {
4526     operand *left = IC_LEFT(ic);
4527     operand *right = IC_RIGHT(ic);
4528     operand *result= IC_RESULT(ic);   
4529
4530
4531         /* Division is a very lengthy algorithm, so it is better
4532          * to call support routines than inlining algorithm.
4533          * Division functions written here just in case someone
4534          * wants to inline and not use the support libraries -- VR */
4535
4536     FENTRY;
4537     
4538     /* assign the amsops */
4539     pic16_aopOp (left,ic,FALSE);
4540     pic16_aopOp (right,ic,FALSE);
4541     pic16_aopOp (result,ic,TRUE);
4542
4543     /* special cases first */
4544     /* both are bits */
4545     if (AOP_TYPE(left) == AOP_CRY &&
4546         AOP_TYPE(right)== AOP_CRY) {
4547         genDivbits(left,right,result);
4548         goto release ;
4549     }
4550
4551     /* if both are of size == 1 */
4552     if (AOP_SIZE(left) == 1 &&
4553         AOP_SIZE(right) == 1 ) {
4554         genDivOneByte(left,right,result);
4555         goto release ;
4556     }
4557
4558     /* should have been converted to function call */
4559     assert(0);
4560 release :
4561     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4562     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4563     pic16_freeAsmop(result,NULL,ic,TRUE); 
4564 }
4565
4566 /*-----------------------------------------------------------------*/
4567 /* genModbits :- modulus of bits                                   */
4568 /*-----------------------------------------------------------------*/
4569 static void genModbits (operand *left, 
4570                         operand *right, 
4571                         operand *result)
4572 {
4573   char *l;
4574
4575     FENTRY;  
4576     
4577     werror(W_POSSBUG2, __FILE__, __LINE__);
4578     /* the result must be bit */    
4579     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4580     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4581
4582     MOVA(l);       
4583
4584     pic16_emitcode("div","ab");
4585     pic16_emitcode("mov","a,b");
4586     pic16_emitcode("rrc","a");
4587     pic16_aopPut(AOP(result),"c",0);
4588 }
4589
4590 /*-----------------------------------------------------------------*/
4591 /* genModOneByte : 8 bit modulus                                   */
4592 /*-----------------------------------------------------------------*/
4593 static void genModOneByte (operand *left,
4594                            operand *right,
4595                            operand *result)
4596 {
4597   sym_link *opetype = operandType(result);
4598   char *l ;
4599   symbol *lbl ;
4600
4601     FENTRY;
4602     werror(W_POSSBUG2, __FILE__, __LINE__);
4603
4604     /* signed or unsigned */
4605     if (SPEC_USIGN(opetype)) {
4606         /* unsigned is easy */
4607         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4608         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4609         MOVA(l);    
4610         pic16_emitcode("div","ab");
4611         pic16_aopPut(AOP(result),"b",0);
4612         return ;
4613     }
4614
4615     /* signed is a little bit more difficult */
4616
4617     /* save the signs of the operands */
4618     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4619     MOVA(l);
4620
4621     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4622     pic16_emitcode("push","acc"); /* save it on the stack */
4623
4624     /* now sign adjust for both left & right */
4625     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4626     MOVA(l);
4627
4628     lbl = newiTempLabel(NULL);
4629     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4630     pic16_emitcode("cpl","a");   
4631     pic16_emitcode("inc","a");
4632     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4633     pic16_emitcode("mov","b,a"); 
4634
4635     /* sign adjust left side */
4636     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4637     MOVA(l);
4638
4639     lbl = newiTempLabel(NULL);
4640     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4641     pic16_emitcode("cpl","a");   
4642     pic16_emitcode("inc","a");
4643     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4644
4645     /* now the multiplication */
4646     pic16_emitcode("div","ab");
4647     /* we are interested in the lower order
4648     only */
4649     lbl = newiTempLabel(NULL);
4650     pic16_emitcode("pop","acc");   
4651     /* if there was an over flow we don't 
4652     adjust the sign of the result */
4653     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4654     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4655     CLRC ;
4656     pic16_emitcode("clr","a");
4657     pic16_emitcode("subb","a,b");
4658     pic16_emitcode("mov","b,a");
4659     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4660
4661     /* now we are done */
4662     pic16_aopPut(AOP(result),"b",0);
4663
4664 }
4665
4666 /*-----------------------------------------------------------------*/
4667 /* genMod - generates code for division                            */
4668 /*-----------------------------------------------------------------*/
4669 static void genMod (iCode *ic)
4670 {
4671   operand *left = IC_LEFT(ic);
4672   operand *right = IC_RIGHT(ic);
4673   operand *result= IC_RESULT(ic);  
4674
4675     FENTRY;
4676     
4677     /* assign the amsops */
4678     pic16_aopOp (left,ic,FALSE);
4679     pic16_aopOp (right,ic,FALSE);
4680     pic16_aopOp (result,ic,TRUE);
4681
4682     /* special cases first */
4683     /* both are bits */
4684     if (AOP_TYPE(left) == AOP_CRY &&
4685         AOP_TYPE(right)== AOP_CRY) {
4686         genModbits(left,right,result);
4687         goto release ;
4688     }
4689
4690     /* if both are of size == 1 */
4691     if (AOP_SIZE(left) == 1 &&
4692         AOP_SIZE(right) == 1 ) {
4693         genModOneByte(left,right,result);
4694         goto release ;
4695     }
4696
4697     /* should have been converted to function call */
4698     assert(0);
4699
4700 release :
4701     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4702     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4703     pic16_freeAsmop(result,NULL,ic,TRUE); 
4704 }
4705
4706 /*-----------------------------------------------------------------*/
4707 /* genIfxJump :- will create a jump depending on the ifx           */
4708 /*-----------------------------------------------------------------*/
4709 /*
4710   note: May need to add parameter to indicate when a variable is in bit space.
4711 */
4712 static void genIfxJump (iCode *ic, char *jval)
4713 {
4714   FENTRY;
4715   
4716     /* if true label then we jump if condition
4717     supplied is true */
4718     if ( IC_TRUE(ic) ) {
4719
4720         if(strcmp(jval,"a") == 0)
4721           emitSKPZ;
4722         else if (strcmp(jval,"c") == 0)
4723           emitSKPNC;
4724         else {
4725           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4726           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4727         }
4728
4729         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4730         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4731
4732     }
4733     else {
4734         /* false label is present */
4735         if(strcmp(jval,"a") == 0)
4736           emitSKPNZ;
4737         else if (strcmp(jval,"c") == 0)
4738           emitSKPC;
4739         else {
4740           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4741           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4742         }
4743
4744         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4745         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4746
4747     }
4748
4749
4750     /* mark the icode as generated */
4751     ic->generated = 1;
4752 }
4753
4754 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4755 {
4756   FENTRY;
4757   
4758     /* if true label then we jump if condition
4759     supplied is true */
4760     if ( IC_TRUE(ic) ) {
4761       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4762       pic16_emitpcode(POC_BTFSC, jop);
4763
4764       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4765       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4766
4767     } else {
4768       /* false label is present */
4769       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4770       pic16_emitpcode(POC_BTFSS, jop);
4771           
4772       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4773       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4774     }
4775
4776
4777     /* mark the icode as generated */
4778     ic->generated = 1;
4779 }
4780
4781 #if 0
4782 // not needed ATM
4783
4784 /*-----------------------------------------------------------------*/
4785 /* genSkip                                                         */
4786 /*-----------------------------------------------------------------*/
4787 static void genSkip(iCode *ifx,int status_bit)
4788 {
4789   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4790   if(!ifx)
4791     return;
4792
4793   if ( IC_TRUE(ifx) ) {
4794     switch(status_bit) {
4795     case 'z':
4796       emitSKPNZ;
4797       break;
4798
4799     case 'c':
4800       emitSKPNC;
4801       break;
4802
4803     case 'd':
4804       emitSKPDC;
4805       break;
4806
4807     }
4808
4809     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4810     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4811
4812   } else {
4813
4814     switch(status_bit) {
4815
4816     case 'z':
4817       emitSKPZ;
4818       break;
4819
4820     case 'c':
4821       emitSKPC;
4822       break;
4823
4824     case 'd':
4825       emitSKPDC;
4826       break;
4827     }
4828     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4829     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4830
4831   }
4832
4833 }
4834 #endif
4835
4836 /*-----------------------------------------------------------------*/
4837 /* genSkipc                                                        */
4838 /*-----------------------------------------------------------------*/
4839 static void genSkipc(resolvedIfx *rifx)
4840 {
4841   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4842   
4843   if(!rifx)
4844     return;
4845
4846   if(rifx->condition)
4847     emitSKPNC;
4848   else
4849     emitSKPC;
4850
4851   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4852   rifx->generated = 1;
4853 }
4854
4855 #if !(USE_SIMPLE_GENCMP)
4856 /*-----------------------------------------------------------------*/
4857 /* genSkipz2                                                       */
4858 /*-----------------------------------------------------------------*/
4859 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4860 {
4861   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4862   
4863   if(!rifx)
4864     return;
4865
4866   if( (rifx->condition ^ invert_condition) & 1)
4867     emitSKPZ;
4868   else
4869     emitSKPNZ;
4870
4871   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4872   rifx->generated = 1;
4873 }
4874 #endif
4875
4876 #if 0
4877 /*-----------------------------------------------------------------*/
4878 /* genSkipz                                                        */
4879 /*-----------------------------------------------------------------*/
4880 static void genSkipz(iCode *ifx, int condition)
4881 {
4882   if(!ifx)
4883     return;
4884
4885   if(condition)
4886     emitSKPNZ;
4887   else
4888     emitSKPZ;
4889
4890   if ( IC_TRUE(ifx) )
4891     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4892   else
4893     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4894
4895   if ( IC_TRUE(ifx) )
4896     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4897   else
4898     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4899
4900 }
4901 #endif
4902
4903 #if !(USE_SIMPLE_GENCMP)
4904 /*-----------------------------------------------------------------*/
4905 /* genSkipCond                                                     */
4906 /*-----------------------------------------------------------------*/
4907 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4908 {
4909   if(!rifx)
4910     return;
4911
4912   if(rifx->condition)
4913     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4914   else
4915     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4916
4917
4918   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4919   rifx->generated = 1;
4920 }
4921 #endif
4922
4923 #if 0
4924 /*-----------------------------------------------------------------*/
4925 /* genChkZeroes :- greater or less than comparison                 */
4926 /*     For each byte in a literal that is zero, inclusive or the   */
4927 /*     the corresponding byte in the operand with W                */
4928 /*     returns true if any of the bytes are zero                   */
4929 /*-----------------------------------------------------------------*/
4930 static int genChkZeroes(operand *op, int lit,  int size)
4931 {
4932
4933   int i;
4934   int flag =1;
4935
4936   while(size--) {
4937     i = (lit >> (size*8)) & 0xff;
4938
4939     if(i==0) {
4940       if(flag) 
4941         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4942       else
4943         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4944       flag = 0;
4945     }
4946   }
4947
4948   return (flag==0);
4949 }
4950 #endif
4951
4952
4953 /*-----------------------------------------------------------------*/
4954 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4955 /*                  aop (if it's NOT a literal) or from lit (if    */
4956 /*                  aop is a literal)                              */
4957 /*-----------------------------------------------------------------*/
4958 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4959   if (aop->type == AOP_LIT) {
4960     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4961   } else {
4962     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4963   }
4964 }
4965
4966 /*-----------------------------------------------------------------*/
4967 /* genCmp :- greater or less than comparison                       */
4968 /*-----------------------------------------------------------------*/
4969
4970 #if USE_SIMPLE_GENCMP           /* { */
4971
4972 /* genCmp performs a left < right comparison, stores
4973  * the outcome in result (if != NULL) and generates
4974  * control flow code for the ifx (if != NULL).
4975  *
4976  * This version leaves in sequences like
4977  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4978  * which should be optmized by the peephole
4979  * optimizer - RN 2005-01-01 */
4980 static void genCmp (operand *left,operand *right,
4981                     operand *result, iCode *ifx, int sign)
4982 {
4983   resolvedIfx rIfx;
4984   int size;
4985   int offs;
4986   symbol *templbl;
4987   operand *dummy;
4988   unsigned long lit;
4989   unsigned long mask;
4990   int performedLt;
4991
4992   FENTRY;
4993   
4994   assert (AOP_SIZE(left) == AOP_SIZE(right));
4995   assert (left && right);
4996
4997   size = AOP_SIZE(right) - 1;
4998   mask = (0x100UL << (size*8)) - 1;
4999   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5000   performedLt = 1;
5001   templbl = NULL;
5002   lit = 0;
5003   
5004   resolveIfx (&rIfx, ifx);
5005
5006   /* handle for special cases */
5007   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5008       return;
5009
5010   /**********************************************************************
5011    * handle bits - bit compares are promoted to int compares seemingly! *
5012    **********************************************************************/
5013 #if 0
5014   // THIS IS COMPLETELY UNTESTED!
5015   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5016     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5017     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5018     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5019
5020     emitSETC;
5021     // 1 < {0,1} is false --> clear C by skipping the next instruction
5022     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5023     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5024     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5025     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5026     emitCLRC; // only skipped for left=0 && right=1
5027
5028     goto correct_result_in_carry;
5029   } // if
5030 #endif
5031
5032   /*************************************************
5033    * make sure that left is register (or the like) *
5034    *************************************************/
5035   if (!isAOP_REGlike(left)) {
5036     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5037     assert (isAOP_LIT(left));
5038     assert (isAOP_REGlike(right));
5039     // swap left and right
5040     // left < right <==> right > left <==> (right >= left + 1)
5041     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5042
5043     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5044       // MAXVALUE < right? always false
5045       if (performedLt) emitCLRC; else emitSETC;
5046       goto correct_result_in_carry;
5047     } // if
5048
5049     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5050     // that's why we handled it above.
5051     lit++;
5052
5053     dummy = left;
5054     left = right;
5055     right = dummy;
5056
5057     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
5058   } else if (isAOP_LIT(right)) {
5059     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5060   } // if
5061
5062   assert (isAOP_REGlike(left)); // left must be register or the like
5063   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5064
5065   /*************************************************
5066    * special cases go here                         *
5067    *************************************************/
5068
5069   if (isAOP_LIT(right)) {
5070     if (!sign) {
5071       // unsigned comparison to a literal
5072       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5073       if (lit == 0) {
5074         // unsigned left < 0? always false
5075         if (performedLt) emitCLRC; else emitSETC;
5076         goto correct_result_in_carry;
5077       }
5078     } else {
5079       // signed comparison to a literal
5080       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5081       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5082         // signed left < 0x80000000? always false
5083         if (performedLt) emitCLRC; else emitSETC;
5084         goto correct_result_in_carry;
5085       } else if (lit == 0) {
5086         // compare left < 0; set CARRY if SIGNBIT(left) is set
5087         if (performedLt) emitSETC; else emitCLRC;
5088         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5089         if (performedLt) emitCLRC; else emitSETC;
5090         goto correct_result_in_carry;
5091       }
5092     } // if (!sign)
5093   } // right is literal
5094
5095   /*************************************************
5096    * perform a general case comparison             *
5097    * make sure we get CARRY==1 <==> left >= right  *
5098    *************************************************/
5099   // compare most significant bytes
5100   //DEBUGpc ("comparing bytes at offset %d", size);
5101   if (!sign) {
5102     // unsigned comparison
5103     mov2w_regOrLit (AOP(right), lit, size);
5104     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5105   } else {
5106     // signed comparison
5107     // (add 2^n to both operands then perform an unsigned comparison)
5108     if (isAOP_LIT(right)) {
5109       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5110       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5111
5112       if (litbyte == 0x80) {
5113         // left >= 0x80 -- always true, but more bytes to come
5114         pic16_mov2w (AOP(left), size);
5115         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5116         emitSETC;
5117       } else {
5118         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5119         pic16_mov2w (AOP(left), size);
5120         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5121         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5122       } // if
5123     } else {
5124       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5125       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5126       pic16_mov2w (AOP(left), size);
5127       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5128       pic16_emitpcode (POC_MOVWF, pctemp);
5129       pic16_mov2w (AOP(right), size);
5130       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5131       pic16_emitpcode (POC_SUBFW, pctemp);
5132       //pic16_popReleaseTempReg(pctemp, 1);
5133     }
5134   } // if (!sign)
5135
5136   // compare remaining bytes (treat as unsigned case from above)
5137   templbl = newiTempLabel ( NULL );
5138   offs = size;
5139   while (offs--) {
5140     //DEBUGpc ("comparing bytes at offset %d", offs);
5141     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5142     mov2w_regOrLit (AOP(right), lit, offs);
5143     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5144   } // while (offs)
5145   pic16_emitpLabel (templbl->key);
5146   goto result_in_carry;
5147
5148 result_in_carry:
5149   
5150   /****************************************************
5151    * now CARRY contains the result of the comparison: *
5152    * SUBWF sets CARRY iff                             *
5153    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5154    * (F=left, W=right)                                *
5155    ****************************************************/
5156
5157   if (performedLt) {
5158     if (result && AOP_TYPE(result) != AOP_CRY) {
5159       // value will be stored
5160       emitTOGC;
5161     } else {
5162       // value wil only be used in the following genSkipc()
5163       rIfx.condition ^= 1;
5164     }
5165   } // if
5166
5167 correct_result_in_carry:
5168
5169   // assign result to variable (if neccessary)
5170   if (result && AOP_TYPE(result) != AOP_CRY) {
5171     //DEBUGpc ("assign result");
5172     size = AOP_SIZE(result);
5173     while (size--) {
5174       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5175     } // while
5176     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5177   } // if (result)
5178
5179   // perform conditional jump
5180   if (ifx) {
5181     //DEBUGpc ("generate control flow");
5182     genSkipc (&rIfx);
5183     ifx->generated = 1;
5184   } // if
5185 }
5186
5187 #elif 1         /* } */
5188                 /* { */
5189       /* original code */
5190 static void genCmp (operand *left,operand *right,
5191                     operand *result, iCode *ifx, int sign)
5192 {
5193   int size; //, offset = 0 ;
5194   unsigned long lit = 0L,i = 0;
5195   resolvedIfx rFalseIfx;
5196   //  resolvedIfx rTrueIfx;
5197   symbol *truelbl;
5198   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5199 /*
5200   if(ifx) {
5201     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5202     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5203   }
5204 */
5205
5206   FENTRY;
5207   
5208   resolveIfx(&rFalseIfx,ifx);
5209   truelbl  = newiTempLabel(NULL);
5210   size = max(AOP_SIZE(left),AOP_SIZE(right));
5211
5212   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5213
5214 #define _swapp
5215
5216   /* if literal is on the right then swap with left */
5217   if ((AOP_TYPE(right) == AOP_LIT)) {
5218     operand *tmp = right ;
5219     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5220     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5221 #ifdef _swapp
5222
5223     lit = (lit - 1) & mask;
5224     right = left;
5225     left = tmp;
5226     rFalseIfx.condition ^= 1;
5227 #endif
5228
5229   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5230     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5231   }
5232
5233
5234   //if(IC_TRUE(ifx) == NULL)
5235   /* if left & right are bit variables */
5236   if (AOP_TYPE(left) == AOP_CRY &&
5237       AOP_TYPE(right) == AOP_CRY ) {
5238     assert (0 && "bit variables used in genCmp");
5239     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5240     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5241   } else {
5242     /* subtract right from left if at the
5243        end the carry flag is set then we know that
5244        left is greater than right */
5245
5246     symbol *lbl  = newiTempLabel(NULL);
5247
5248 #if 0
5249         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5250                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5251 #endif
5252
5253 #ifndef _swapp
5254     if(AOP_TYPE(right) == AOP_LIT) {
5255
5256       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5257
5258       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5259
5260       /* special cases */
5261
5262       if(lit == 0) {
5263
5264         if(sign != 0) 
5265           genSkipCond(&rFalseIfx,left,size-1,7);
5266         else 
5267           /* no need to compare to 0...*/
5268           /* NOTE: this is a de-generate compare that most certainly 
5269            *       creates some dead code. */
5270           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5271
5272         if(ifx) ifx->generated = 1;
5273         return;
5274
5275       }
5276       size--;
5277
5278       if(size == 0) {
5279         //i = (lit >> (size*8)) & 0xff;
5280         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5281         
5282         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5283
5284         i = ((0-lit) & 0xff);
5285         if(sign) {
5286           if( i == 0x81) { 
5287             /* lit is 0x7f, all signed chars are less than
5288              * this except for 0x7f itself */
5289             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5290             genSkipz2(&rFalseIfx,0);
5291           } else {
5292             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5293             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5294             genSkipc(&rFalseIfx);
5295           }
5296
5297         } else {
5298           if(lit == 1) {
5299             genSkipz2(&rFalseIfx,1);
5300           } else {
5301             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5302             genSkipc(&rFalseIfx);
5303           }
5304         }
5305
5306         if(ifx) ifx->generated = 1;
5307         return;
5308       }
5309
5310       /* chars are out of the way. now do ints and longs */
5311
5312
5313       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5314         
5315       /* special cases */
5316
5317       if(sign) {
5318
5319         if(lit == 0) {
5320           genSkipCond(&rFalseIfx,left,size,7);
5321           if(ifx) ifx->generated = 1;
5322           return;
5323         }
5324
5325         if(lit <0x100) {
5326           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5327
5328           //rFalseIfx.condition ^= 1;
5329           //genSkipCond(&rFalseIfx,left,size,7);
5330           //rFalseIfx.condition ^= 1;
5331
5332           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5333           if(rFalseIfx.condition)
5334             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5335           else
5336             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5337
5338           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5339           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5340           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5341
5342           while(size > 1)
5343             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5344
5345           if(rFalseIfx.condition) {
5346             emitSKPZ;
5347             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5348
5349           } else {
5350             emitSKPNZ;
5351           }
5352
5353           genSkipc(&rFalseIfx);
5354           pic16_emitpLabel(truelbl->key);
5355           if(ifx) ifx->generated = 1;
5356           return;
5357
5358         }
5359
5360         if(size == 1) {
5361
5362           if( (lit & 0xff) == 0) {
5363             /* lower byte is zero */
5364             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5365             i = ((lit >> 8) & 0xff) ^0x80;
5366             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5367             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5368             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5369             genSkipc(&rFalseIfx);
5370
5371
5372             if(ifx) ifx->generated = 1;
5373             return;
5374
5375           }
5376         } else {
5377           /* Special cases for signed longs */
5378           if( (lit & 0xffffff) == 0) {
5379             /* lower byte is zero */
5380             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5381             i = ((lit >> 8*3) & 0xff) ^0x80;
5382             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5383             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5384             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5385             genSkipc(&rFalseIfx);
5386
5387
5388             if(ifx) ifx->generated = 1;
5389             return;
5390
5391           }
5392
5393         }
5394
5395
5396         if(lit & (0x80 << (size*8))) {
5397           /* lit is negative */
5398           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5399
5400           //genSkipCond(&rFalseIfx,left,size,7);
5401
5402           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5403
5404           if(rFalseIfx.condition)
5405             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5406           else
5407             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5408
5409
5410         } else {
5411           /* lit is positive */
5412           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5413           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5414           if(rFalseIfx.condition)
5415             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5416           else
5417             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5418
5419         }
5420
5421         /*
5422           This works, but is only good for ints.
5423           It also requires a "known zero" register.
5424           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5425           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5426           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5427           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5428           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5429           genSkipc(&rFalseIfx);
5430
5431           pic16_emitpLabel(truelbl->key);
5432           if(ifx) ifx->generated = 1;
5433           return;
5434         **/
5435           
5436         /* There are no more special cases, so perform a general compare */
5437   
5438         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5439         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5440
5441         while(size--) {
5442
5443           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5444           emitSKPNZ;
5445           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5446         }
5447         //rFalseIfx.condition ^= 1;
5448         genSkipc(&rFalseIfx);
5449
5450         pic16_emitpLabel(truelbl->key);
5451
5452         if(ifx) ifx->generated = 1;
5453         return;
5454
5455
5456       }
5457
5458
5459       /* sign is out of the way. So now do an unsigned compare */
5460       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5461
5462
5463       /* General case - compare to an unsigned literal on the right.*/
5464
5465       i = (lit >> (size*8)) & 0xff;
5466       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5467       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5468       while(size--) {
5469         i = (lit >> (size*8)) & 0xff;
5470
5471         if(i) {
5472           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5473           emitSKPNZ;
5474           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5475         } else {
5476           /* this byte of the lit is zero, 
5477            *if it's not the last then OR in the variable */
5478           if(size)
5479             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5480         }
5481       }
5482
5483
5484       pic16_emitpLabel(lbl->key);
5485 //      pic16_emitpLabel(truelbl->key);
5486       //if(emitFinalCheck)
5487       genSkipc(&rFalseIfx);
5488       if(sign)
5489         pic16_emitpLabel(truelbl->key);
5490
5491       if(ifx) ifx->generated = 1;
5492       return;
5493
5494
5495     }
5496 #endif  // _swapp
5497
5498     if(AOP_TYPE(left) == AOP_LIT) {
5499       //symbol *lbl = newiTempLabel(NULL);
5500
5501       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5502
5503
5504       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5505
5506       /* Special cases */
5507       if((lit == 0) && (sign == 0)){
5508
5509         size--;
5510         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5511         while(size) 
5512           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5513
5514         genSkipz2(&rFalseIfx,0);
5515         if(ifx) ifx->generated = 1;
5516         return;
5517       }
5518
5519       if(size==1) {
5520         /* Special cases */
5521         lit &= 0xff;
5522         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5523           /* degenerate compare can never be true */
5524           if(rFalseIfx.condition == 0)
5525             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5526
5527           if(ifx) ifx->generated = 1;
5528           return;
5529         }
5530
5531         if(sign) {
5532           /* signed comparisons to a literal byte */
5533
5534           int lp1 = (lit+1) & 0xff;
5535
5536           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5537           switch (lp1) {
5538           case 0:
5539             rFalseIfx.condition ^= 1;
5540             genSkipCond(&rFalseIfx,right,0,7);
5541             break;
5542           case 0x7f:
5543             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5544             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5545             genSkipz2(&rFalseIfx,1);
5546             break;
5547           default:
5548             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5549             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5550             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5551             rFalseIfx.condition ^= 1;
5552             genSkipc(&rFalseIfx);
5553             break;
5554           }
5555         } else {
5556           /* unsigned comparisons to a literal byte */
5557
5558           switch(lit & 0xff ) {
5559           case 0:
5560             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5561             genSkipz2(&rFalseIfx,0);
5562             break;
5563           case 0x7f:
5564             rFalseIfx.condition ^= 1;
5565             genSkipCond(&rFalseIfx,right,0,7);
5566             break;
5567
5568           default:
5569             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5570             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5571             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5572             rFalseIfx.condition ^= 1;
5573             if (AOP_TYPE(result) == AOP_CRY)
5574               genSkipc(&rFalseIfx);
5575             else {
5576               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5577               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5578             }         
5579             break;
5580           }
5581         }
5582
5583         if(ifx) ifx->generated = 1;
5584         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5585                 goto check_carry;
5586         return;
5587
5588       } else {
5589
5590         /* Size is greater than 1 */
5591
5592         if(sign) {
5593           int lp1 = lit+1;
5594
5595           size--;
5596
5597           if(lp1 == 0) {
5598             /* this means lit = 0xffffffff, or -1 */
5599
5600
5601             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5602             rFalseIfx.condition ^= 1;
5603             genSkipCond(&rFalseIfx,right,size,7);
5604             if(ifx) ifx->generated = 1;
5605
5606             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5607               goto check_carry;
5608
5609             return;
5610           }
5611
5612           if(lit == 0) {
5613             int s = size;
5614
5615             if(rFalseIfx.condition) {
5616               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5617               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5618             }
5619
5620             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5621             while(size--)
5622               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5623
5624
5625             emitSKPZ;
5626             if(rFalseIfx.condition) {
5627               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5628               pic16_emitpLabel(truelbl->key);
5629             }else {
5630               rFalseIfx.condition ^= 1;
5631               genSkipCond(&rFalseIfx,right,s,7);
5632             }
5633
5634             if(ifx) ifx->generated = 1;
5635
5636             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5637               goto check_carry;
5638
5639             return;
5640           }
5641
5642           if((size == 1) &&  (0 == (lp1&0xff))) {
5643             /* lower byte of signed word is zero */
5644             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5645             i = ((lp1 >> 8) & 0xff) ^0x80;
5646             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5647             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5648             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5649
5650             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5651               emitTOGC;
5652               if(ifx) ifx->generated = 1;
5653               goto check_carry;
5654             } else {
5655               rFalseIfx.condition ^= 1;
5656               genSkipc(&rFalseIfx);
5657               if(ifx) ifx->generated = 1;
5658             }
5659
5660             return;
5661           }
5662
5663           if(lit & (0x80 << (size*8))) {
5664             /* Lit is less than zero */
5665             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5666             //rFalseIfx.condition ^= 1;
5667             //genSkipCond(&rFalseIfx,left,size,7);
5668             //rFalseIfx.condition ^= 1;
5669             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5670             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5671
5672             if(rFalseIfx.condition)
5673               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5674             else
5675               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5676
5677
5678           } else {
5679             /* Lit is greater than or equal to zero */
5680             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5681             //rFalseIfx.condition ^= 1;
5682             //genSkipCond(&rFalseIfx,right,size,7);
5683             //rFalseIfx.condition ^= 1;
5684
5685             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5686             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5687
5688             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5689             if(rFalseIfx.condition)
5690               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5691             else
5692               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5693
5694           }
5695
5696           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5697           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5698
5699           while(size--) {
5700
5701             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5702             emitSKPNZ;
5703             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5704           }
5705           rFalseIfx.condition ^= 1;
5706           //rFalseIfx.condition = 1;
5707           genSkipc(&rFalseIfx);
5708
5709           pic16_emitpLabel(truelbl->key);
5710
5711           if(ifx) ifx->generated = 1;
5712
5713
5714           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5715             goto check_carry;
5716
5717           return;
5718           // end of if (sign)
5719         } else {
5720
5721           /* compare word or long to an unsigned literal on the right.*/
5722
5723
5724           size--;
5725           if(lit < 0xff) {
5726             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5727             switch (lit) {
5728             case 0:
5729               break; /* handled above */
5730 /*
5731             case 0xff:
5732               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5733               while(size--)
5734                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5735               genSkipz2(&rFalseIfx,0);
5736               break;
5737 */
5738             default:
5739               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5740               while(--size)
5741                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5742
5743               emitSKPZ;
5744               if(rFalseIfx.condition)
5745                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5746               else
5747                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5748
5749
5750               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5751               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5752
5753               rFalseIfx.condition ^= 1;
5754               genSkipc(&rFalseIfx);
5755             }
5756
5757             pic16_emitpLabel(truelbl->key);
5758
5759             if(ifx) ifx->generated = 1;
5760
5761             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5762               goto check_carry;
5763
5764             return;
5765           }
5766
5767
5768           lit++;
5769           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5770           i = (lit >> (size*8)) & 0xff;
5771
5772           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5773           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5774
5775           while(size--) {
5776             i = (lit >> (size*8)) & 0xff;
5777
5778             if(i) {
5779               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5780               emitSKPNZ;
5781               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5782             } else {
5783               /* this byte of the lit is zero, 
5784                * if it's not the last then OR in the variable */
5785               if(size)
5786                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5787             }
5788           }
5789
5790
5791           pic16_emitpLabel(lbl->key);
5792
5793           rFalseIfx.condition ^= 1;
5794
5795           genSkipc(&rFalseIfx);
5796         }
5797
5798         if(sign)
5799           pic16_emitpLabel(truelbl->key);
5800         if(ifx) ifx->generated = 1;
5801
5802             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5803               goto check_carry;
5804
5805         return;
5806       }
5807     }
5808     /* Compare two variables */
5809
5810     DEBUGpic16_emitcode(";sign","%d",sign);
5811
5812     size--;
5813     if(sign) {
5814       /* Sigh. thus sucks... */
5815       if(size) {
5816         pCodeOp *pctemp;
5817         
5818         pctemp = pic16_popGetTempReg(1);
5819         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5820         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5821         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5822         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5823         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5824         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5825         pic16_popReleaseTempReg(pctemp, 1);
5826       } else {
5827         /* Signed char comparison */
5828         /* Special thanks to Nikolai Golovchenko for this snippet */
5829         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5830         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5831         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5832         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5833         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5834         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5835
5836         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5837         genSkipc(&rFalseIfx);
5838           
5839         if(ifx) ifx->generated = 1;
5840
5841             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5842               goto check_carry;
5843
5844         return;
5845       }
5846
5847     } else {
5848
5849       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5850       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5851     }
5852
5853
5854     /* The rest of the bytes of a multi-byte compare */
5855     while (size) {
5856
5857       emitSKPZ;
5858       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5859       size--;
5860
5861       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5862       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5863
5864
5865     }
5866
5867     pic16_emitpLabel(lbl->key);
5868
5869     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5870     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5871         (AOP_TYPE(result) == AOP_REG)) {
5872       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5873       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5874     } else {
5875       genSkipc(&rFalseIfx);
5876     }         
5877     //genSkipc(&rFalseIfx);
5878     if(ifx) ifx->generated = 1;
5879
5880
5881             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5882               goto check_carry;
5883
5884     return;
5885
5886   }
5887
5888 check_carry:
5889   if ((AOP_TYPE(result) != AOP_CRY) 
5890         && AOP_SIZE(result)) {
5891     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5892
5893     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5894
5895     pic16_outBitC(result);
5896   } else {
5897     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5898     /* if the result is used in the next
5899        ifx conditional branch then generate
5900        code a little differently */
5901     if (ifx )
5902       genIfxJump (ifx,"c");
5903     else
5904       pic16_outBitC(result);
5905     /* leave the result in acc */
5906   }
5907
5908 }
5909
5910 #elif 0 /* VR version of genCmp() */    /* } else { */
5911
5912 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5913 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5914         operand *result, int offset, int invert_op)
5915 {
5916   /* add code here */
5917   
5918   /* check condition, > or < ?? */
5919   if(rIfx->condition != 0)invert_op ^= 1;
5920   
5921   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5922
5923   if(!ifx)invert_op ^= 1;
5924
5925   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5926       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5927   
5928   /* do selection */
5929   if(!invert_op)return POC_CPFSGT;
5930   else return POC_CPFSLT;
5931 }
5932
5933 static int compareAopfirstpass=1;
5934
5935 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5936             operand *oper, int offset, operand *result,
5937             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5938             symbol *tlbl)
5939 {
5940   int op;
5941   symbol *truelbl;
5942
5943   /* invert if there is a result to be loaded, in order to fit,
5944    * SETC/CLRC sequence */
5945   if(AOP_SIZE(result))invert_op ^= 1;
5946
5947 //  if(sign && !offset)invert_op ^= 1;
5948   
5949 //  if(sign)invert_op ^= 1;
5950   
5951   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5952
5953   if(AOP_SIZE(result) && compareAopfirstpass) {
5954     if(!ifx) {
5955       if(pcop2)
5956         pic16_emitpcode(POC_SETF, pcop2);
5957       else
5958         emitSETC;
5959     } else {
5960       if(pcop2)
5961         pic16_emitpcode(POC_CLRF, pcop2);
5962       else
5963         emitCLRC;
5964     }
5965   }
5966
5967   compareAopfirstpass = 0;
5968
5969       /* there is a bug when comparing operands with size > 1,
5970        * because higher bytes can be equal and test should be performed
5971        * to the next lower byte, current algorithm, considers operands
5972        * inequal in these cases! -- VR 20041107 */
5973
5974     
5975   if(pcop)
5976     pic16_emitpcode(op, pcop);
5977   else
5978     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5979
5980
5981   if((!sign || !offset) && AOP_SIZE(result)) {
5982     if(!ifx) {
5983       if(pcop2)
5984         pic16_emitpcode(POC_CLRF, pcop2);
5985         else
5986         emitCLRC;
5987     } else {
5988       if(pcop2)
5989         pic16_emitpcode(POC_SETF, pcop2);
5990       else
5991         emitSETC;
5992     }
5993     
5994     /* don't emit final branch (offset == 0) */
5995     if(offset) {
5996
5997       if(pcop2)
5998         pic16_emitpcode(POC_RRCF, pcop2);
5999
6000       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6001     }
6002   } else {
6003     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6004       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6005             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6006
6007       truelbl = newiTempLabel( NULL );
6008       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6009       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6010         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6011       else
6012         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6013       pic16_emitpLabel(truelbl->key);
6014     } else {
6015       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6016     }
6017   }
6018 }
6019
6020 static void genCmp (operand *left, operand *right,
6021                     operand *result, iCode *ifx, int sign)
6022 {
6023   int size, cmpop=1;
6024   long lit = 0L;
6025   resolvedIfx rFalseIfx;
6026   symbol *falselbl, *tlbl;
6027
6028     FENTRY;
6029     
6030     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6031
6032     resolveIfx(&rFalseIfx, ifx);
6033     size = max(AOP_SIZE(left), AOP_SIZE(right));
6034     
6035     /* if left & right are bit variables */
6036     if(AOP_TYPE(left) == AOP_CRY
6037       && AOP_TYPE(right) == AOP_CRY ) {
6038
6039         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6040         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6041         
6042         werror(W_POSSBUG2, __FILE__, __LINE__);
6043         exit(-1);
6044     }
6045     
6046     /* if literal is on the right then swap with left */
6047     if((AOP_TYPE(right) == AOP_LIT)) {
6048       operand *tmp = right ;
6049 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
6050
6051         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6052
6053 //      lit = (lit - 1) & mask;
6054         right = left;
6055         left = tmp;
6056         rFalseIfx.condition ^= 1;               /* reverse compare */
6057     } else
6058     if ((AOP_TYPE(left) == AOP_LIT)) {
6059       /* float compares are handled by support functions */
6060       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6061     }
6062
6063     /* actual comparing algorithm */
6064 //    size = AOP_SIZE( right );
6065
6066     falselbl = newiTempLabel( NULL );
6067     if(AOP_TYPE(left) == AOP_LIT) {
6068       /* compare to literal */
6069       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6070       
6071       if(sign) {
6072         pCodeOp *pct, *pct2;
6073         symbol *tlbl1;
6074
6075         /* signed compare */
6076         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6077
6078         pct = pic16_popCopyReg(&pic16_pc_prodl);
6079         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6080         tlbl = newiTempLabel( NULL );
6081         
6082         /* first compare signs:
6083          *  a. if both are positive, compare just like unsigned
6084          *  b. if both are negative, invert cmpop, compare just like unsigned
6085          *  c. if different signs, determine the result directly */
6086
6087         size--;
6088
6089 #if 1
6090         /* { */
6091         tlbl1 = newiTempLabel( NULL );
6092 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6093
6094         if(lit > 0) {
6095
6096           /* literal is zero or positive:
6097            *  a. if carry is zero, too, continue compare,
6098            *  b. if carry is set, then continue depending on cmpop ^ condition:
6099            *    1. '<' return false (literal < variable),
6100            *    2. '>' return true (literal > variable) */
6101 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6102           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6103           
6104           
6105           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6106           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6107         } else 
6108         if(lit < 0) {
6109           
6110           /* literal is negative:
6111            *  a. if carry is set, too, continue compare,
6112            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6113            *    1. '<' return true (literal < variable),
6114            *    2. '>' return false (literal > variable) */
6115 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6116           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6117           
6118           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6119           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6120         }
6121 #if 1
6122         else {
6123           /* lit == 0 */
6124           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6125           
6126           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6127           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6128         }
6129 #endif
6130         
6131         
6132         pic16_emitpLabel( tlbl1->key );
6133 #endif  /* } */
6134
6135         compareAopfirstpass=1;
6136 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6137 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6138 //        pic16_emitpcode(POC_MOVWF, pct);
6139
6140 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6141         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6142 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6143         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6144
6145         /* generic case */        
6146           while( size-- ) {
6147 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6148 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6149 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6150 //            pic16_emitpcode(POC_MOVWF, pct);
6151
6152 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6153             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6154             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6155 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6156 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6157           }
6158 //        }
6159         
6160         if(ifx)ifx->generated = 1;
6161
6162         if(AOP_SIZE(result)) {
6163           pic16_emitpLabel(tlbl->key);
6164           pic16_emitpLabel(falselbl->key);
6165           pic16_outBitOp( result, pct2 );
6166         } else {
6167           pic16_emitpLabel(tlbl->key);
6168         }
6169       } else {
6170
6171         /* unsigned compare */      
6172         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6173     
6174         compareAopfirstpass=1;
6175         while(size--) {
6176           
6177           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6178           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6179
6180         }
6181         if(ifx)ifx->generated = 1;
6182
6183         if(AOP_SIZE(result)) {
6184           pic16_emitpLabel(falselbl->key);
6185           pic16_outBitC( result );
6186         }
6187
6188       }
6189     } else {
6190       /* compare registers */
6191       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6192
6193
6194       if(sign) {
6195         pCodeOp *pct, *pct2;
6196         
6197         /* signed compare */
6198         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6199
6200         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6201         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6202         tlbl = newiTempLabel( NULL );
6203         
6204         compareAopfirstpass=1;
6205
6206         size--;
6207         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6208 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6209         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6210         pic16_emitpcode(POC_MOVWF, pct);
6211
6212         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6213 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6214         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6215
6216         /* WREG already holds left + 0x80 */
6217         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6218         
6219         while( size-- ) {
6220           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6221 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6222           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6223           pic16_emitpcode(POC_MOVWF, pct);
6224                 
6225           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6226 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6227           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6228
6229           /* WREG already holds left + 0x80 */
6230           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6231 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6232         }
6233         
6234         if(ifx)ifx->generated = 1;
6235
6236         if(AOP_SIZE(result)) {
6237           pic16_emitpLabel(tlbl->key);
6238           pic16_emitpLabel(falselbl->key);
6239           pic16_outBitOp( result, pct2 );
6240         } else {
6241           pic16_emitpLabel(tlbl->key);
6242         }
6243
6244       } else {
6245         /* unsigned compare */      
6246         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6247
6248         compareAopfirstpass=1;
6249         while(size--) {
6250           
6251           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6252           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6253
6254         }
6255
6256         if(ifx)ifx->generated = 1;
6257         if(AOP_SIZE(result)) {
6258
6259           pic16_emitpLabel(falselbl->key);
6260           pic16_outBitC( result );
6261         }
6262
6263       }
6264     }
6265 }
6266
6267 #endif  /* } */
6268
6269
6270
6271 /*-----------------------------------------------------------------*/
6272 /* genCmpGt :- greater than comparison                             */
6273 /*-----------------------------------------------------------------*/
6274 static void genCmpGt (iCode *ic, iCode *ifx)
6275 {
6276   operand *left, *right, *result;
6277   sym_link *letype , *retype;
6278   int sign ;
6279
6280     FENTRY;
6281     
6282     left = IC_LEFT(ic);
6283     right= IC_RIGHT(ic);
6284     result = IC_RESULT(ic);
6285
6286     letype = getSpec(operandType(left));
6287     retype =getSpec(operandType(right));
6288     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6289     /* assign the amsops */
6290     pic16_aopOp (left,ic,FALSE);
6291     pic16_aopOp (right,ic,FALSE);
6292     pic16_aopOp (result,ic,TRUE);
6293
6294     genCmp(right, left, result, ifx, sign);
6295
6296     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6297     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6298     pic16_freeAsmop(result,NULL,ic,TRUE); 
6299 }
6300
6301 /*-----------------------------------------------------------------*/
6302 /* genCmpLt - less than comparisons                                */
6303 /*-----------------------------------------------------------------*/
6304 static void genCmpLt (iCode *ic, iCode *ifx)
6305 {
6306   operand *left, *right, *result;
6307   sym_link *letype , *retype;
6308   int sign ;
6309
6310     FENTRY;
6311
6312     left = IC_LEFT(ic);
6313     right= IC_RIGHT(ic);
6314     result = IC_RESULT(ic);
6315
6316     letype = getSpec(operandType(left));
6317     retype =getSpec(operandType(right));
6318     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6319
6320     /* assign the amsops */
6321     pic16_aopOp (left,ic,FALSE);
6322     pic16_aopOp (right,ic,FALSE);
6323     pic16_aopOp (result,ic,TRUE);
6324
6325     genCmp(left, right, result, ifx, sign);
6326
6327     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6328     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6329     pic16_freeAsmop(result,NULL,ic,TRUE); 
6330 }
6331
6332 #if 0
6333 // not needed ATM
6334 // FIXME reenable literal optimisation when the pic16 port is stable
6335
6336 /*-----------------------------------------------------------------*/
6337 /* genc16bit2lit - compare a 16 bit value to a literal             */
6338 /*-----------------------------------------------------------------*/
6339 static void genc16bit2lit(operand *op, int lit, int offset)
6340 {
6341   int i;
6342
6343   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6344   if( (lit&0xff) == 0) 
6345     i=1;
6346   else
6347     i=0;
6348
6349   switch( BYTEofLONG(lit,i)) { 
6350   case 0:
6351     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6352     break;
6353   case 1:
6354     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6355     break;
6356   case 0xff:
6357     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6358     break;
6359   default:
6360     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6361     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6362   }
6363
6364   i ^= 1;
6365
6366   switch( BYTEofLONG(lit,i)) { 
6367   case 0:
6368     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6369     break;
6370   case 1:
6371     emitSKPNZ;
6372     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6373     break;
6374   case 0xff:
6375     emitSKPNZ;
6376     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6377     break;
6378   default:
6379     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6380     emitSKPNZ;
6381     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6382
6383   }
6384
6385 }
6386 #endif
6387
6388 #if 0
6389 // not needed ATM
6390 /*-----------------------------------------------------------------*/
6391 /* gencjneshort - compare and jump if not equal                    */
6392 /*-----------------------------------------------------------------*/
6393 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6394 {
6395   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6396   int offset = 0;
6397   int res_offset = 0;  /* the result may be a different size then left or right */
6398   int res_size = AOP_SIZE(result);
6399   resolvedIfx rIfx;
6400   symbol *lbl, *lbl_done;
6401
6402   unsigned long lit = 0L;
6403   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6404
6405   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6406   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6407   if(result)
6408     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6409   resolveIfx(&rIfx,ifx);
6410   lbl =  newiTempLabel(NULL);
6411   lbl_done =  newiTempLabel(NULL);
6412
6413
6414   /* if the left side is a literal or 
6415      if the right is in a pointer register and left 
6416      is not */
6417   if ((AOP_TYPE(left) == AOP_LIT) || 
6418       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6419     operand *t = right;
6420     right = left;
6421     left = t;
6422   }
6423   if(AOP_TYPE(right) == AOP_LIT)
6424     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6425
6426   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6427     preserve_result = 1;
6428
6429   if(result && !preserve_result)
6430     {
6431       int i;
6432       for(i = 0; i < AOP_SIZE(result); i++)
6433         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6434     }
6435
6436
6437   /* if the right side is a literal then anything goes */
6438   if (AOP_TYPE(right) == AOP_LIT &&
6439       AOP_TYPE(left) != AOP_DIR ) {
6440     switch(size) {
6441     case 2:
6442       genc16bit2lit(left, lit, 0);
6443       emitSKPZ;
6444       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6445       break;
6446     default:
6447       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6448       while (size--) {
6449         if(lit & 0xff) {
6450           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6451           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6452         } else {
6453           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6454         }
6455
6456         emitSKPZ;
6457         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6458         offset++;
6459         if(res_offset < res_size-1)
6460           res_offset++;
6461         lit >>= 8;
6462       }
6463       break;
6464     }
6465   }
6466
6467   /* if the right side is in a register or in direct space or
6468      if the left is a pointer register & right is not */    
6469   else if (AOP_TYPE(right) == AOP_REG ||
6470            AOP_TYPE(right) == AOP_DIR || 
6471            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6472            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6473     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6474     int lbl_key = lbl->key;
6475
6476     if(result) {
6477       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6478       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6479     }else {
6480       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6481       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6482               __FUNCTION__,__LINE__);
6483       return;
6484     }
6485    
6486 /*     switch(size) { */
6487 /*     case 2: */
6488 /*       genc16bit2lit(left, lit, 0); */
6489 /*       emitSKPNZ; */
6490 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6491 /*       break; */
6492 /*     default: */
6493     while (size--) {
6494       int emit_skip=1;
6495       if((AOP_TYPE(left) == AOP_DIR) && 
6496          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6497
6498         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6499         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6500
6501       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6502             
6503         switch (lit & 0xff) {
6504         case 0:
6505           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6506           break;
6507         case 1:
6508           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6509           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6510           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6511           emit_skip=0;
6512           break;
6513         case 0xff:
6514           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6515           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6516           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6517           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6518           emit_skip=0;
6519           break;
6520         default:
6521           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6522           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6523         }
6524         lit >>= 8;
6525
6526       } else {
6527         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6528       }
6529       if(emit_skip) {
6530         if(AOP_TYPE(result) == AOP_CRY) {
6531           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6532           if(rIfx.condition)
6533             emitSKPNZ;
6534           else
6535             emitSKPZ;
6536           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6537         } else {
6538           /* fix me. probably need to check result size too */
6539           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6540           if(rIfx.condition)
6541             emitSKPZ;
6542           else
6543             emitSKPNZ;
6544           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6545           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6546         }
6547         if(ifx)
6548           ifx->generated=1;
6549       }
6550       emit_skip++;
6551       offset++;
6552       if(res_offset < res_size-1)
6553         res_offset++;
6554     }
6555 /*       break; */
6556 /*     } */
6557   } else if(AOP_TYPE(right) == AOP_REG &&
6558             AOP_TYPE(left) != AOP_DIR){
6559
6560     while(size--) {
6561       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6562       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6563       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6564       if(rIfx.condition)
6565         emitSKPNZ;
6566       else
6567         emitSKPZ;
6568       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6569       offset++;
6570       if(res_offset < res_size-1)
6571         res_offset++;
6572     }
6573       
6574   }else{
6575     /* right is a pointer reg need both a & b */
6576     while(size--) {
6577       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6578       if(strcmp(l,"b"))
6579         pic16_emitcode("mov","b,%s",l);
6580       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6581       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6582       offset++;
6583     }
6584   }
6585
6586   if(result && preserve_result)
6587     {
6588       int i;
6589       for(i = 0; i < AOP_SIZE(result); i++)
6590         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6591     }
6592
6593   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6594
6595   if(result && preserve_result)
6596     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6597
6598   if(!rIfx.condition)
6599     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6600
6601   pic16_emitpLabel(lbl->key);
6602
6603   if(result && preserve_result)
6604     {
6605       int i;
6606       for(i = 0; i < AOP_SIZE(result); i++)
6607         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6608
6609       pic16_emitpLabel(lbl_done->key);
6610    }
6611
6612   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6613
6614   if(ifx)
6615     ifx->generated = 1;
6616 }
6617 #endif
6618
6619 #if 0
6620 /*-----------------------------------------------------------------*/
6621 /* gencjne - compare and jump if not equal                         */
6622 /*-----------------------------------------------------------------*/
6623 static void gencjne(operand *left, operand *right, iCode *ifx)
6624 {
6625     symbol *tlbl  = newiTempLabel(NULL);
6626
6627     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6628     gencjneshort(left, right, lbl);
6629
6630     pic16_emitcode("mov","a,%s",one);
6631     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6632     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6633     pic16_emitcode("clr","a");
6634     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6635
6636     pic16_emitpLabel(lbl->key);
6637     pic16_emitpLabel(tlbl->key);
6638
6639 }
6640 #endif
6641
6642
6643 /*-----------------------------------------------------------------*/
6644 /* is_LitOp - check if operand has to be treated as literal        */
6645 /*-----------------------------------------------------------------*/
6646 static bool is_LitOp(operand *op)
6647 {
6648   return ((AOP_TYPE(op) == AOP_LIT)
6649       || ( (AOP_TYPE(op) == AOP_PCODE)
6650           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6651               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6652 }
6653
6654 /*-----------------------------------------------------------------*/
6655 /* is_LitAOp - check if operand has to be treated as literal        */
6656 /*-----------------------------------------------------------------*/
6657 static bool is_LitAOp(asmop *aop)
6658 {
6659   return ((aop->type == AOP_LIT)
6660       || ( (aop->type == AOP_PCODE)
6661           && ( (aop->aopu.pcop->type == PO_LITERAL)
6662               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6663 }
6664
6665
6666
6667 /*-----------------------------------------------------------------*/
6668 /* genCmpEq - generates code for equal to                          */
6669 /*-----------------------------------------------------------------*/
6670 static void genCmpEq (iCode *ic, iCode *ifx)
6671 {
6672   operand *left, *right, *result;
6673   symbol *falselbl = newiTempLabel(NULL);
6674   symbol *donelbl = newiTempLabel(NULL);
6675
6676   int preserve_result = 0;
6677   int generate_result = 0;
6678   int i=0;
6679   unsigned long lit = -1;
6680
6681   FENTRY;
6682   
6683   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6684   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6685   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6686  
6687   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6688
6689   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6690     {
6691       werror(W_POSSBUG2, __FILE__, __LINE__);
6692       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6693       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6694       goto release;
6695     }
6696
6697   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6698     {
6699       operand *tmp = right ;
6700       right = left;
6701       left = tmp;
6702     }
6703
6704   if (AOP_TYPE(right) == AOP_LIT) {
6705     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6706   }
6707
6708   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6709     preserve_result = 1;
6710
6711   if(result && AOP_SIZE(result))
6712     generate_result = 1;
6713
6714   if(generate_result && !preserve_result)
6715     {
6716       for(i = 0; i < AOP_SIZE(result); i++)
6717         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6718     }
6719
6720   for(i=0; i < AOP_SIZE(left); i++)
6721     {
6722       if(AOP_TYPE(left) != AOP_ACC)
6723         {
6724           if(is_LitOp(left))
6725             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6726           else
6727             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6728         }
6729       if(is_LitOp(right)) {
6730         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6731           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6732         }
6733       } else
6734         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6735
6736       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6737     }
6738
6739   // result == true
6740
6741   if(generate_result && preserve_result)
6742     {
6743       for(i = 0; i < AOP_SIZE(result); i++)
6744         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6745     }
6746
6747   if(generate_result)
6748     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6749
6750   if(generate_result && preserve_result)
6751     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6752
6753   if(ifx && IC_TRUE(ifx))
6754     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6755
6756   if(ifx && IC_FALSE(ifx))
6757     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6758
6759   pic16_emitpLabel(falselbl->key);
6760
6761   // result == false
6762
6763   if(ifx && IC_FALSE(ifx))
6764     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6765
6766   if(generate_result && preserve_result)
6767     {
6768       for(i = 0; i < AOP_SIZE(result); i++)
6769         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6770     }
6771
6772   pic16_emitpLabel(donelbl->key);
6773
6774   if(ifx)
6775     ifx->generated = 1;
6776
6777 release:
6778   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6779   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6780   pic16_freeAsmop(result,NULL,ic,TRUE);
6781
6782 }
6783
6784
6785 #if 0
6786 // old version kept for reference
6787
6788 /*-----------------------------------------------------------------*/
6789 /* genCmpEq - generates code for equal to                          */
6790 /*-----------------------------------------------------------------*/
6791 static void genCmpEq (iCode *ic, iCode *ifx)
6792 {
6793     operand *left, *right, *result;
6794     unsigned long lit = 0L;
6795     int size,offset=0;
6796     symbol *falselbl  = newiTempLabel(NULL);
6797
6798
6799     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6800
6801     if(ifx)
6802       DEBUGpic16_emitcode ("; ifx is non-null","");
6803     else
6804       DEBUGpic16_emitcode ("; ifx is null","");
6805
6806     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6807     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6808     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6809
6810     size = max(AOP_SIZE(left),AOP_SIZE(right));
6811
6812     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6813
6814     /* if literal, literal on the right or 
6815     if the right is in a pointer register and left 
6816     is not */
6817     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6818         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6819       operand *tmp = right ;
6820       right = left;
6821       left = tmp;
6822     }
6823
6824
6825     if(ifx && !AOP_SIZE(result)){
6826         symbol *tlbl;
6827         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6828         /* if they are both bit variables */
6829         if (AOP_TYPE(left) == AOP_CRY &&
6830             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6831                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6832             if(AOP_TYPE(right) == AOP_LIT){
6833                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6834                 if(lit == 0L){
6835                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6836                     pic16_emitcode("cpl","c");
6837                 } else if(lit == 1L) {
6838                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6839                 } else {
6840                     pic16_emitcode("clr","c");
6841                 }
6842                 /* AOP_TYPE(right) == AOP_CRY */
6843             } else {
6844                 symbol *lbl = newiTempLabel(NULL);
6845                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6846                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6847                 pic16_emitcode("cpl","c");
6848                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6849             }
6850             /* if true label then we jump if condition
6851             supplied is true */
6852             tlbl = newiTempLabel(NULL);
6853             if ( IC_TRUE(ifx) ) {
6854                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6855                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6856             } else {
6857                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6858                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6859             }
6860             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6861
6862                 {
6863                 /* left and right are both bit variables, result is carry */
6864                         resolvedIfx rIfx;
6865               
6866                         resolveIfx(&rIfx,ifx);
6867
6868                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6869                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6870                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6871                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6872                         genSkipz2(&rIfx,0);
6873                 }
6874         } else {
6875
6876                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6877
6878                         /* They're not both bit variables. Is the right a literal? */
6879                         if(AOP_TYPE(right) == AOP_LIT) {
6880                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6881             
6882                         switch(size) {
6883
6884                                 case 1:
6885                                         switch(lit & 0xff) {
6886                                                 case 1:
6887                                                                 if ( IC_TRUE(ifx) ) {
6888                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6889                                                                         emitSKPNZ;
6890                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6891                                                                 } else {
6892                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6893                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6894                                                                 }
6895                                                                 break;
6896                                                 case 0xff:
6897                                                                 if ( IC_TRUE(ifx) ) {
6898                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6899                                                                         emitSKPNZ;
6900                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6901                                                                 } else {
6902                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6903                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6904                                                                 }
6905                                                                 break;
6906                                                 default:
6907                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6908                                                                 if(lit)
6909                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6910                                                                 genSkip(ifx,'z');
6911                                         } // switch lit
6912
6913
6914                                         /* end of size == 1 */
6915                                         break;
6916               
6917                                 case 2:
6918                                         genc16bit2lit(left,lit,offset);
6919                                         genSkip(ifx,'z');
6920                                         break;
6921                                         /* end of size == 2 */
6922
6923                                 default:
6924                                         /* size is 4 */
6925                                         if(lit==0) {
6926                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6927                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6928                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6929                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6930                                                 genSkip(ifx,'z');
6931                                         } else {
6932                                                 /* search for patterns that can be optimized */
6933
6934                                                 genc16bit2lit(left,lit,0);
6935                                                 lit >>= 16;
6936                                                 if(lit) {
6937                                                                 if(IC_TRUE(ifx))
6938                                                                 emitSKPZ; // if hi word unequal
6939                                                                 else
6940                                                                 emitSKPNZ; // if hi word equal
6941                                                                 // fail early
6942                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6943                                                         genc16bit2lit(left,lit,2);
6944                                                         genSkip(ifx,'z');
6945                                                 } else {
6946                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6947                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6948                                                         genSkip(ifx,'z');
6949                                                 }
6950                                         }
6951                                                 pic16_emitpLabel(falselbl->key);
6952                                                 break;
6953
6954                         } // switch size
6955           
6956                         ifx->generated = 1;
6957                         goto release ;
6958             
6959
6960           } else if(AOP_TYPE(right) == AOP_CRY ) {
6961             /* we know the left is not a bit, but that the right is */
6962             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6963             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6964                       pic16_popGet(AOP(right),offset));
6965             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6966
6967             /* if the two are equal, then W will be 0 and the Z bit is set
6968              * we could test Z now, or go ahead and check the high order bytes if
6969              * the variable we're comparing is larger than a byte. */
6970
6971             while(--size)
6972               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6973
6974             if ( IC_TRUE(ifx) ) {
6975               emitSKPNZ;
6976               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6977               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6978             } else {
6979               emitSKPZ;
6980               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6981               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6982             }
6983
6984           } else {
6985             /* They're both variables that are larger than bits */
6986             int s = size;
6987
6988             tlbl = newiTempLabel(NULL);
6989
6990             while(size--) {
6991               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6992               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6993
6994               if ( IC_TRUE(ifx) ) {
6995                 if(size) {
6996                   emitSKPZ;
6997                 
6998                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6999
7000                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7001                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7002                 } else {
7003                   emitSKPNZ;
7004
7005                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7006
7007
7008                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7009                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7010                 }
7011               } else {
7012                 emitSKPZ;
7013
7014                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7015
7016                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7017                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7018               }
7019               offset++;
7020             }
7021             if(s>1 && IC_TRUE(ifx)) {
7022               pic16_emitpLabel(tlbl->key);
7023               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7024             }
7025           }
7026         }
7027         /* mark the icode as generated */
7028         ifx->generated = 1;
7029         goto release ;
7030     }
7031
7032     /* if they are both bit variables */
7033     if (AOP_TYPE(left) == AOP_CRY &&
7034         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7035         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7036         if(AOP_TYPE(right) == AOP_LIT){
7037             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7038             if(lit == 0L){
7039                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7040                 pic16_emitcode("cpl","c");
7041             } else if(lit == 1L) {
7042                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7043             } else {
7044                 pic16_emitcode("clr","c");
7045             }
7046             /* AOP_TYPE(right) == AOP_CRY */
7047         } else {
7048             symbol *lbl = newiTempLabel(NULL);
7049             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7050             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7051             pic16_emitcode("cpl","c");
7052             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7053         }
7054         /* c = 1 if egal */
7055         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7056             pic16_outBitC(result);
7057             goto release ;
7058         }
7059         if (ifx) {
7060             genIfxJump (ifx,"c");
7061             goto release ;
7062         }
7063         /* if the result is used in an arithmetic operation
7064         then put the result in place */
7065         pic16_outBitC(result);
7066     } else {
7067       
7068       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7069       gencjne(left,right,result,ifx);
7070 /*
7071       if(ifx) 
7072         gencjne(left,right,newiTempLabel(NULL));
7073       else {
7074         if(IC_TRUE(ifx)->key)
7075           gencjne(left,right,IC_TRUE(ifx)->key);
7076         else
7077           gencjne(left,right,IC_FALSE(ifx)->key);
7078         ifx->generated = 1;
7079         goto release ;
7080       }
7081       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7082         pic16_aopPut(AOP(result),"a",0);
7083         goto release ;
7084       }
7085
7086       if (ifx) {
7087         genIfxJump (ifx,"a");
7088         goto release ;
7089       }
7090 */
7091       /* if the result is used in an arithmetic operation
7092          then put the result in place */
7093 /*
7094       if (AOP_TYPE(result) != AOP_CRY) 
7095         pic16_outAcc(result);
7096 */
7097       /* leave the result in acc */
7098     }
7099
7100 release:
7101     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7102     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7103     pic16_freeAsmop(result,NULL,ic,TRUE);
7104 }
7105 #endif
7106
7107 /*-----------------------------------------------------------------*/
7108 /* ifxForOp - returns the icode containing the ifx for operand     */
7109 /*-----------------------------------------------------------------*/
7110 static iCode *ifxForOp ( operand *op, iCode *ic )
7111 {
7112   FENTRY2;
7113
7114     /* if true symbol then needs to be assigned */
7115     if (IS_TRUE_SYMOP(op))
7116         return NULL ;
7117
7118     /* if this has register type condition and
7119     the next instruction is ifx with the same operand
7120     and live to of the operand is upto the ifx only then */
7121     if (ic->next
7122         && ic->next->op == IFX
7123         && IC_COND(ic->next)->key == op->key
7124         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7125         ) {
7126                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7127           return ic->next;
7128     }
7129
7130     /*
7131     if (ic->next &&
7132         ic->next->op == IFX &&
7133         IC_COND(ic->next)->key == op->key) {
7134       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7135       return ic->next;
7136     }
7137     */
7138
7139     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7140     if (ic->next &&
7141         ic->next->op == IFX)
7142       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7143
7144     if (ic->next &&
7145         ic->next->op == IFX &&
7146         IC_COND(ic->next)->key == op->key) {
7147       DEBUGpic16_emitcode ("; "," key is okay");
7148       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7149                            OP_SYMBOL(op)->liveTo,
7150                            ic->next->seq);
7151     }
7152
7153 #if 0
7154     /* the code below is completely untested
7155      * it just allows ulong2fs.c compile -- VR */
7156          
7157     ic = ic->next;
7158     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7159                                         __FILE__, __FUNCTION__, __LINE__);
7160         
7161     /* if this has register type condition and
7162     the next instruction is ifx with the same operand
7163     and live to of the operand is upto the ifx only then */
7164     if (ic->next &&
7165         ic->next->op == IFX &&
7166         IC_COND(ic->next)->key == op->key &&
7167         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7168         return ic->next;
7169
7170     if (ic->next &&
7171         ic->next->op == IFX &&
7172         IC_COND(ic->next)->key == op->key) {
7173       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7174       return ic->next;
7175     }
7176
7177     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7178                                         __FILE__, __FUNCTION__, __LINE__);
7179
7180 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7181 #endif
7182
7183     return NULL;
7184 }
7185 /*-----------------------------------------------------------------*/
7186 /* genAndOp - for && operation                                     */
7187 /*-----------------------------------------------------------------*/
7188 static void genAndOp (iCode *ic)
7189 {
7190   operand *left,*right, *result;
7191 /*     symbol *tlbl; */
7192
7193     FENTRY;
7194
7195     /* note here that && operations that are in an
7196     if statement are taken away by backPatchLabels
7197     only those used in arthmetic operations remain */
7198     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7199     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7200     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7201
7202     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7203
7204     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7205     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7206     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7207
7208     /* if both are bit variables */
7209 /*     if (AOP_TYPE(left) == AOP_CRY && */
7210 /*         AOP_TYPE(right) == AOP_CRY ) { */
7211 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7212 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7213 /*         pic16_outBitC(result); */
7214 /*     } else { */
7215 /*         tlbl = newiTempLabel(NULL); */
7216 /*         pic16_toBoolean(left);     */
7217 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7218 /*         pic16_toBoolean(right); */
7219 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7220 /*         pic16_outBitAcc(result); */
7221 /*     } */
7222
7223     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7224     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7225     pic16_freeAsmop(result,NULL,ic,TRUE);
7226 }
7227
7228
7229 /*-----------------------------------------------------------------*/
7230 /* genOrOp - for || operation                                      */
7231 /*-----------------------------------------------------------------*/
7232 /*
7233   tsd pic port -
7234   modified this code, but it doesn't appear to ever get called
7235 */
7236
7237 static void genOrOp (iCode *ic)
7238 {
7239   operand *left,*right, *result;
7240   symbol *tlbl;
7241
7242     FENTRY;  
7243
7244   /* note here that || operations that are in an
7245     if statement are taken away by backPatchLabels
7246     only those used in arthmetic operations remain */
7247     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7248     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7249     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7250
7251     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7252
7253     /* if both are bit variables */
7254     if (AOP_TYPE(left) == AOP_CRY &&
7255         AOP_TYPE(right) == AOP_CRY ) {
7256       pic16_emitcode("clrc","");
7257       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7258                AOP(left)->aopu.aop_dir,
7259                AOP(left)->aopu.aop_dir);
7260       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7261                AOP(right)->aopu.aop_dir,
7262                AOP(right)->aopu.aop_dir);
7263       pic16_emitcode("setc","");
7264
7265     } else {
7266         tlbl = newiTempLabel(NULL);
7267         pic16_toBoolean(left);
7268         emitSKPZ;
7269         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7270         pic16_toBoolean(right);
7271         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7272
7273         pic16_outBitAcc(result);
7274     }
7275
7276     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7277     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7278     pic16_freeAsmop(result,NULL,ic,TRUE);            
7279 }
7280
7281 /*-----------------------------------------------------------------*/
7282 /* isLiteralBit - test if lit == 2^n                               */
7283 /*-----------------------------------------------------------------*/
7284 static int isLiteralBit(unsigned long lit)
7285 {
7286     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7287     0x100L,0x200L,0x400L,0x800L,
7288     0x1000L,0x2000L,0x4000L,0x8000L,
7289     0x10000L,0x20000L,0x40000L,0x80000L,
7290     0x100000L,0x200000L,0x400000L,0x800000L,
7291     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7292     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7293     int idx;
7294     
7295     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7296     for(idx = 0; idx < 32; idx++)
7297         if(lit == pw[idx])
7298             return idx+1;
7299     return 0;
7300 }
7301
7302 /*-----------------------------------------------------------------*/
7303 /* continueIfTrue -                                                */
7304 /*-----------------------------------------------------------------*/
7305 static void continueIfTrue (iCode *ic)
7306 {
7307   FENTRY;
7308   if(IC_TRUE(ic))
7309     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7310   ic->generated = 1;
7311 }
7312
7313 /*-----------------------------------------------------------------*/
7314 /* jmpIfTrue -                                                     */
7315 /*-----------------------------------------------------------------*/
7316 static void jumpIfTrue (iCode *ic)
7317 {
7318   FENTRY;
7319   if(!IC_TRUE(ic))
7320     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7321   ic->generated = 1;
7322 }
7323
7324 /*-----------------------------------------------------------------*/
7325 /* jmpTrueOrFalse -                                                */
7326 /*-----------------------------------------------------------------*/
7327 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7328 {
7329   // ugly but optimized by peephole
7330   FENTRY;
7331   if(IC_TRUE(ic)){
7332     symbol *nlbl = newiTempLabel(NULL);
7333       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7334       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7335       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7336       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7337   } else {
7338     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7339     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7340   }
7341   ic->generated = 1;
7342 }
7343
7344 /*-----------------------------------------------------------------*/
7345 /* genAnd  - code for and                                          */
7346 /*-----------------------------------------------------------------*/
7347 static void genAnd (iCode *ic, iCode *ifx)
7348 {
7349   operand *left, *right, *result;
7350   int size, offset=0;  
7351   unsigned long lit = 0L;
7352   int bytelit = 0;
7353   resolvedIfx rIfx;
7354
7355     FENTRY;
7356     
7357   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7358   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7359   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7360
7361   resolveIfx(&rIfx,ifx);
7362
7363   /* if left is a literal & right is not then exchange them */
7364   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7365       AOP_NEEDSACC(left)) {
7366     operand *tmp = right ;
7367     right = left;
7368     left = tmp;
7369   }
7370
7371   /* if result = right then exchange them */
7372   if(pic16_sameRegs(AOP(result),AOP(right))){
7373     operand *tmp = right ;
7374     right = left;
7375     left = tmp;
7376   }
7377
7378   /* if right is bit then exchange them */
7379   if (AOP_TYPE(right) == AOP_CRY &&
7380       AOP_TYPE(left) != AOP_CRY){
7381     operand *tmp = right ;
7382     right = left;
7383     left = tmp;
7384   }
7385   if(AOP_TYPE(right) == AOP_LIT)
7386     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7387
7388   size = AOP_SIZE(result);
7389
7390   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7391
7392   // if(bit & yy)
7393   // result = bit & yy;
7394   if (AOP_TYPE(left) == AOP_CRY){
7395     // c = bit & literal;
7396     if(AOP_TYPE(right) == AOP_LIT){
7397       if(lit & 1) {
7398         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7399           // no change
7400           goto release;
7401         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7402       } else {
7403         // bit(result) = 0;
7404         if(size && (AOP_TYPE(result) == AOP_CRY)){
7405           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7406           goto release;
7407         }
7408         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7409           jumpIfTrue(ifx);
7410           goto release;
7411         }
7412         pic16_emitcode("clr","c");
7413       }
7414     } else {
7415       if (AOP_TYPE(right) == AOP_CRY){
7416         // c = bit & bit;
7417         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7418         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7419       } else {
7420         // c = bit & val;
7421         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7422         // c = lsb
7423         pic16_emitcode("rrc","a");
7424         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7425       }
7426     }
7427     // bit = c
7428     // val = c
7429     if(size)
7430       pic16_outBitC(result);
7431     // if(bit & ...)
7432     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7433       genIfxJump(ifx, "c");           
7434     goto release ;
7435   }
7436
7437   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7438   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7439   if((AOP_TYPE(right) == AOP_LIT) &&
7440      (AOP_TYPE(result) == AOP_CRY) &&
7441      (AOP_TYPE(left) != AOP_CRY)){
7442     int posbit = isLiteralBit(lit);
7443     /* left &  2^n */
7444     if(posbit){
7445       posbit--;
7446       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7447       // bit = left & 2^n
7448       if(size)
7449         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7450       // if(left &  2^n)
7451       else{
7452         if(ifx){
7453 /*
7454           if(IC_TRUE(ifx)) {
7455             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7456             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7457           } else {
7458             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7459             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7460           }
7461 */
7462         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7463         size = AOP_SIZE(left);
7464
7465         {
7466           int bp = posbit, ofs=0;
7467           
7468             while(bp > 7) {
7469               bp -= 8;
7470               ofs++;
7471             }
7472         
7473           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7474                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7475
7476         }
7477 /*
7478           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7479                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7480 */
7481           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7482           
7483           ifx->generated = 1;
7484         }
7485         goto release;
7486       }
7487     } else {
7488       symbol *tlbl = newiTempLabel(NULL);
7489       int sizel = AOP_SIZE(left);
7490
7491       if(size)
7492         emitSETC;
7493
7494       while(sizel--) {
7495         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7496
7497           /* patch provided by Aaron Colwell */
7498           if((posbit = isLiteralBit(bytelit)) != 0) {
7499               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7500                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7501                                                 (posbit-1),0, PO_GPR_REGISTER));
7502
7503               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7504 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7505           } else {
7506               if (bytelit == 0xff) {
7507                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7508                    * a peephole could optimize it out -- VR */
7509                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7510               } else {
7511                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7512                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7513               }
7514
7515               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7516                             pic16_popGetLabel(tlbl->key));
7517           }
7518         
7519 #if 0
7520           /* old code, left here for reference -- VR 09/2004 */
7521           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7522           // byte ==  2^n ?
7523           if((posbit = isLiteralBit(bytelit)) != 0)
7524             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7525           else{
7526             if(bytelit != 0x0FFL)
7527               pic16_emitcode("anl","a,%s",
7528                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7529             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7530           }
7531 #endif
7532         }
7533         offset++;
7534       }
7535       // bit = left & literal
7536       if(size) {
7537         emitCLRC;
7538         pic16_emitpLabel(tlbl->key);
7539       }
7540       // if(left & literal)
7541       else {
7542         if(ifx) {
7543           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7544           ifx->generated = 1;
7545         }
7546         pic16_emitpLabel(tlbl->key);
7547         goto release;
7548       }
7549     }
7550
7551     pic16_outBitC(result);
7552     goto release ;
7553   }
7554
7555   /* if left is same as result */
7556   if(pic16_sameRegs(AOP(result),AOP(left))){
7557     int know_W = -1;
7558     for(;size--; offset++,lit>>=8) {
7559       if(AOP_TYPE(right) == AOP_LIT){
7560         switch(lit & 0xff) {
7561         case 0x00:
7562           /*  and'ing with 0 has clears the result */
7563 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7564           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7565           break;
7566         case 0xff:
7567           /* and'ing with 0xff is a nop when the result and left are the same */
7568           break;
7569
7570         default:
7571           {
7572             int p = pic16_my_powof2( (~lit) & 0xff );
7573             if(p>=0) {
7574               /* only one bit is set in the literal, so use a bcf instruction */
7575 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7576               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7577
7578             } else {
7579               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7580               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7581               if(know_W != (lit&0xff))
7582                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7583               know_W = lit &0xff;
7584               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7585             }
7586           }    
7587         }
7588       } else {
7589         if (AOP_TYPE(left) == AOP_ACC) {
7590           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7591         } else {                    
7592           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7593           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7594
7595         }
7596       }
7597     }
7598
7599   } else {
7600     // left & result in different registers
7601     if(AOP_TYPE(result) == AOP_CRY){
7602       // result = bit
7603       // if(size), result in bit
7604       // if(!size && ifx), conditional oper: if(left & right)
7605       symbol *tlbl = newiTempLabel(NULL);
7606       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7607       if(size)
7608         pic16_emitcode("setb","c");
7609       while(sizer--){
7610         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7611         pic16_emitcode("anl","a,%s",
7612                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7613         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7614         offset++;
7615       }
7616       if(size){
7617         CLRC;
7618         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7619         pic16_outBitC(result);
7620       } else if(ifx)
7621         jmpTrueOrFalse(ifx, tlbl);
7622     } else {
7623       for(;(size--);offset++) {
7624         // normal case
7625         // result = left & right
7626         if(AOP_TYPE(right) == AOP_LIT){
7627           int t = (lit >> (offset*8)) & 0x0FFL;
7628           switch(t) { 
7629           case 0x00:
7630             pic16_emitcode("clrf","%s",
7631                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7632             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7633             break;
7634           case 0xff:
7635             pic16_emitcode("movf","%s,w",
7636                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7637             pic16_emitcode("movwf","%s",
7638                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7639             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7640             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7641             break;
7642           default:
7643             pic16_emitcode("movlw","0x%x",t);
7644             pic16_emitcode("andwf","%s,w",
7645                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7646             pic16_emitcode("movwf","%s",
7647                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7648               
7649             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7650             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7651             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7652           }
7653           continue;
7654         }
7655
7656         if (AOP_TYPE(left) == AOP_ACC) {
7657           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7658           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7659         } else {
7660           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7661           pic16_emitcode("andwf","%s,w",
7662                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7663           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7664           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7665         }
7666         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7667         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7668       }
7669     }
7670   }
7671
7672   release :
7673     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7674   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7675   pic16_freeAsmop(result,NULL,ic,TRUE);     
7676 }
7677
7678 /*-----------------------------------------------------------------*/
7679 /* genOr  - code for or                                            */
7680 /*-----------------------------------------------------------------*/
7681 static void genOr (iCode *ic, iCode *ifx)
7682 {
7683     operand *left, *right, *result;
7684     int size, offset=0;
7685     unsigned long lit = 0L;
7686
7687     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7688
7689     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7690     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7691     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7692
7693     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7694
7695     /* if left is a literal & right is not then exchange them */
7696     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7697         AOP_NEEDSACC(left)) {
7698         operand *tmp = right ;
7699         right = left;
7700         left = tmp;
7701     }
7702
7703     /* if result = right then exchange them */
7704     if(pic16_sameRegs(AOP(result),AOP(right))){
7705         operand *tmp = right ;
7706         right = left;
7707         left = tmp;
7708     }
7709
7710     /* if right is bit then exchange them */
7711     if (AOP_TYPE(right) == AOP_CRY &&
7712         AOP_TYPE(left) != AOP_CRY){
7713         operand *tmp = right ;
7714         right = left;
7715         left = tmp;
7716     }
7717
7718     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7719
7720     if(AOP_TYPE(right) == AOP_LIT)
7721         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7722
7723     size = AOP_SIZE(result);
7724
7725     // if(bit | yy)
7726     // xx = bit | yy;
7727     if (AOP_TYPE(left) == AOP_CRY){
7728         if(AOP_TYPE(right) == AOP_LIT){
7729             // c = bit & literal;
7730             if(lit){
7731                 // lit != 0 => result = 1
7732                 if(AOP_TYPE(result) == AOP_CRY){
7733                   if(size)
7734                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7735                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7736                   //     AOP(result)->aopu.aop_dir,
7737                   //     AOP(result)->aopu.aop_dir);
7738                     else if(ifx)
7739                         continueIfTrue(ifx);
7740                     goto release;
7741                 }
7742             } else {
7743                 // lit == 0 => result = left
7744                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7745                     goto release;
7746                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7747             }
7748         } else {
7749             if (AOP_TYPE(right) == AOP_CRY){
7750               if(pic16_sameRegs(AOP(result),AOP(left))){
7751                 // c = bit | bit;
7752                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7753                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7754                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7755
7756                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7757                          AOP(result)->aopu.aop_dir,
7758                          AOP(result)->aopu.aop_dir);
7759                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7760                          AOP(right)->aopu.aop_dir,
7761                          AOP(right)->aopu.aop_dir);
7762                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7763                          AOP(result)->aopu.aop_dir,
7764                          AOP(result)->aopu.aop_dir);
7765               } else {
7766                 if( AOP_TYPE(result) == AOP_ACC) {
7767                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7768                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7769                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7770                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7771
7772                 } else {
7773
7774                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7775                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7776                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7777                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7778
7779                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7780                                  AOP(result)->aopu.aop_dir,
7781                                  AOP(result)->aopu.aop_dir);
7782                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7783                                  AOP(right)->aopu.aop_dir,
7784                                  AOP(right)->aopu.aop_dir);
7785                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7786                                  AOP(left)->aopu.aop_dir,
7787                                  AOP(left)->aopu.aop_dir);
7788                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7789                                  AOP(result)->aopu.aop_dir,
7790                                  AOP(result)->aopu.aop_dir);
7791                 }
7792               }
7793             } else {
7794                 // c = bit | val;
7795                 symbol *tlbl = newiTempLabel(NULL);
7796                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7797
7798
7799                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7800                 if( AOP_TYPE(right) == AOP_ACC) {
7801                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7802                   emitSKPNZ;
7803                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7804                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7805                 }
7806
7807
7808
7809                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7810                     pic16_emitcode(";XXX setb","c");
7811                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7812                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7813                 pic16_toBoolean(right);
7814                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7815                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7816                     jmpTrueOrFalse(ifx, tlbl);
7817                     goto release;
7818                 } else {
7819                     CLRC;
7820                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7821                 }
7822             }
7823         }
7824         // bit = c
7825         // val = c
7826         if(size)
7827             pic16_outBitC(result);
7828         // if(bit | ...)
7829         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7830             genIfxJump(ifx, "c");           
7831         goto release ;
7832     }
7833
7834     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7835     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7836     if((AOP_TYPE(right) == AOP_LIT) &&
7837        (AOP_TYPE(result) == AOP_CRY) &&
7838        (AOP_TYPE(left) != AOP_CRY)){
7839         if(lit){
7840           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7841             // result = 1
7842             if(size)
7843                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7844             else 
7845                 continueIfTrue(ifx);
7846             goto release;
7847         } else {
7848           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7849             // lit = 0, result = boolean(left)
7850             if(size)
7851                 pic16_emitcode(";XXX setb","c");
7852             pic16_toBoolean(right);
7853             if(size){
7854                 symbol *tlbl = newiTempLabel(NULL);
7855                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7856                 CLRC;
7857                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7858             } else {
7859                 genIfxJump (ifx,"a");
7860                 goto release;
7861             }
7862         }
7863         pic16_outBitC(result);
7864         goto release ;
7865     }
7866
7867     /* if left is same as result */
7868     if(pic16_sameRegs(AOP(result),AOP(left))){
7869       int know_W = -1;
7870       for(;size--; offset++,lit>>=8) {
7871         if(AOP_TYPE(right) == AOP_LIT){
7872           if((lit & 0xff) == 0)
7873             /*  or'ing with 0 has no effect */
7874             continue;
7875           else {
7876             int p = pic16_my_powof2(lit & 0xff);
7877             if(p>=0) {
7878               /* only one bit is set in the literal, so use a bsf instruction */
7879               pic16_emitpcode(POC_BSF,
7880                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7881             } else {
7882               if(know_W != (lit & 0xff))
7883                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7884               know_W = lit & 0xff;
7885               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7886             }
7887                     
7888           }
7889         } else {
7890           if (AOP_TYPE(left) == AOP_ACC) {
7891             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7892             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7893           } else {                  
7894             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7895             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7896
7897             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7898             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7899
7900           }
7901         }
7902       }
7903     } else {
7904         // left & result in different registers
7905         if(AOP_TYPE(result) == AOP_CRY){
7906             // result = bit
7907             // if(size), result in bit
7908             // if(!size && ifx), conditional oper: if(left | right)
7909             symbol *tlbl = newiTempLabel(NULL);
7910             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7911             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7912
7913
7914             if(size)
7915                 pic16_emitcode(";XXX setb","c");
7916             while(sizer--){
7917                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7918                 pic16_emitcode(";XXX orl","a,%s",
7919                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7920                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7921                 offset++;
7922             }
7923             if(size){
7924                 CLRC;
7925                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7926                 pic16_outBitC(result);
7927             } else if(ifx)
7928                 jmpTrueOrFalse(ifx, tlbl);
7929         } else for(;(size--);offset++){
7930           // normal case
7931           // result = left & right
7932           if(AOP_TYPE(right) == AOP_LIT){
7933             int t = (lit >> (offset*8)) & 0x0FFL;
7934             switch(t) { 
7935             case 0x00:
7936               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7937               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7938
7939               pic16_emitcode("movf","%s,w",
7940                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7941               pic16_emitcode("movwf","%s",
7942                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7943               break;
7944             default:
7945               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7946               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7947               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7948
7949               pic16_emitcode("movlw","0x%x",t);
7950               pic16_emitcode("iorwf","%s,w",
7951                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7952               pic16_emitcode("movwf","%s",
7953                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7954               
7955             }
7956             continue;
7957           }
7958
7959           // faster than result <- left, anl result,right
7960           // and better if result is SFR
7961           if (AOP_TYPE(left) == AOP_ACC) {
7962             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7963             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7964           } else {
7965             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7966             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7967
7968             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7969             pic16_emitcode("iorwf","%s,w",
7970                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7971           }
7972           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7973           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7974         }
7975     }
7976
7977 release :
7978     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7979     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7980     pic16_freeAsmop(result,NULL,ic,TRUE);     
7981 }
7982
7983 /*-----------------------------------------------------------------*/
7984 /* genXor - code for xclusive or                                   */
7985 /*-----------------------------------------------------------------*/
7986 static void genXor (iCode *ic, iCode *ifx)
7987 {
7988   operand *left, *right, *result;
7989   int size, offset=0;
7990   unsigned long lit = 0L;
7991
7992   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7993
7994   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7995   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7996   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7997
7998   /* if left is a literal & right is not ||
7999      if left needs acc & right does not */
8000   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8001       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8002     operand *tmp = right ;
8003     right = left;
8004     left = tmp;
8005   }
8006
8007   /* if result = right then exchange them */
8008   if(pic16_sameRegs(AOP(result),AOP(right))){
8009     operand *tmp = right ;
8010     right = left;
8011     left = tmp;
8012   }
8013
8014   /* if right is bit then exchange them */
8015   if (AOP_TYPE(right) == AOP_CRY &&
8016       AOP_TYPE(left) != AOP_CRY){
8017     operand *tmp = right ;
8018     right = left;
8019     left = tmp;
8020   }
8021   if(AOP_TYPE(right) == AOP_LIT)
8022     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8023
8024   size = AOP_SIZE(result);
8025
8026   // if(bit ^ yy)
8027   // xx = bit ^ yy;
8028   if (AOP_TYPE(left) == AOP_CRY){
8029     if(AOP_TYPE(right) == AOP_LIT){
8030       // c = bit & literal;
8031       if(lit>>1){
8032         // lit>>1  != 0 => result = 1
8033         if(AOP_TYPE(result) == AOP_CRY){
8034           if(size)
8035             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8036             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8037           else if(ifx)
8038             continueIfTrue(ifx);
8039           goto release;
8040         }
8041         pic16_emitcode("setb","c");
8042       } else{
8043         // lit == (0 or 1)
8044         if(lit == 0){
8045           // lit == 0, result = left
8046           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8047             goto release;
8048           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8049         } else{
8050           // lit == 1, result = not(left)
8051           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8052             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8053             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8054             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8055             goto release;
8056           } else {
8057             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8058             pic16_emitcode("cpl","c");
8059           }
8060         }
8061       }
8062
8063     } else {
8064       // right != literal
8065       symbol *tlbl = newiTempLabel(NULL);
8066       if (AOP_TYPE(right) == AOP_CRY){
8067         // c = bit ^ bit;
8068         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8069       }
8070       else{
8071         int sizer = AOP_SIZE(right);
8072         // c = bit ^ val
8073         // if val>>1 != 0, result = 1
8074         pic16_emitcode("setb","c");
8075         while(sizer){
8076           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8077           if(sizer == 1)
8078             // test the msb of the lsb
8079             pic16_emitcode("anl","a,#0xfe");
8080           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8081           sizer--;
8082         }
8083         // val = (0,1)
8084         pic16_emitcode("rrc","a");
8085       }
8086       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8087       pic16_emitcode("cpl","c");
8088       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8089     }
8090     // bit = c
8091     // val = c
8092     if(size)
8093       pic16_outBitC(result);
8094     // if(bit | ...)
8095     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8096       genIfxJump(ifx, "c");           
8097     goto release ;
8098   }
8099
8100   if(pic16_sameRegs(AOP(result),AOP(left))){
8101     /* if left is same as result */
8102     for(;size--; offset++) {
8103       if(AOP_TYPE(right) == AOP_LIT){
8104         int t  = (lit >> (offset*8)) & 0x0FFL;
8105         if(t == 0x00L)
8106           continue;
8107         else
8108           if (IS_AOP_PREG(left)) {
8109             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8110             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8111             pic16_aopPut(AOP(result),"a",offset);
8112           } else {
8113             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8114             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8115             pic16_emitcode("xrl","%s,%s",
8116                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8117                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8118           }
8119       } else {
8120         if (AOP_TYPE(left) == AOP_ACC)
8121           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8122         else {
8123           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8124           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8125 /*
8126           if (IS_AOP_PREG(left)) {
8127             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8128             pic16_aopPut(AOP(result),"a",offset);
8129           } else
8130             pic16_emitcode("xrl","%s,a",
8131                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8132 */
8133         }
8134       }
8135     }
8136   } else {
8137     // left & result in different registers
8138     if(AOP_TYPE(result) == AOP_CRY){
8139       // result = bit
8140       // if(size), result in bit
8141       // if(!size && ifx), conditional oper: if(left ^ right)
8142       symbol *tlbl = newiTempLabel(NULL);
8143       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8144       if(size)
8145         pic16_emitcode("setb","c");
8146       while(sizer--){
8147         if((AOP_TYPE(right) == AOP_LIT) &&
8148            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8149           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8150         } else {
8151           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8152           pic16_emitcode("xrl","a,%s",
8153                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8154         }
8155         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8156         offset++;
8157       }
8158       if(size){
8159         CLRC;
8160         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8161         pic16_outBitC(result);
8162       } else if(ifx)
8163         jmpTrueOrFalse(ifx, tlbl);
8164     } else for(;(size--);offset++){
8165       // normal case
8166       // result = left & right
8167       if(AOP_TYPE(right) == AOP_LIT){
8168         int t = (lit >> (offset*8)) & 0x0FFL;
8169         switch(t) { 
8170         case 0x00:
8171           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8172           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8173           pic16_emitcode("movf","%s,w",
8174                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8175           pic16_emitcode("movwf","%s",
8176                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8177           break;
8178         case 0xff:
8179           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8180           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8181           pic16_emitcode("comf","%s,w",
8182                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8183           pic16_emitcode("movwf","%s",
8184                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8185           break;
8186         default:
8187           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8188           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8189           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8190           pic16_emitcode("movlw","0x%x",t);
8191           pic16_emitcode("xorwf","%s,w",
8192                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8193           pic16_emitcode("movwf","%s",
8194                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8195
8196         }
8197         continue;
8198       }
8199
8200       // faster than result <- left, anl result,right
8201       // and better if result is SFR
8202       if (AOP_TYPE(left) == AOP_ACC) {
8203         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8204         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8205       } else {
8206         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8207         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8208         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8209         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8210       }
8211       if ( AOP_TYPE(result) != AOP_ACC){
8212         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8213         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8214       }
8215     }
8216   }
8217
8218   release :
8219     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8220   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8221   pic16_freeAsmop(result,NULL,ic,TRUE);     
8222 }
8223
8224 /*-----------------------------------------------------------------*/
8225 /* genInline - write the inline code out                           */
8226 /*-----------------------------------------------------------------*/
8227 static void genInline (iCode *ic)
8228 {
8229   char *buffer, *bp, *bp1;
8230     
8231         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8232
8233         _G.inLine += (!options.asmpeep);
8234
8235         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8236         strcpy(buffer,IC_INLINE(ic));
8237         
8238         while((bp1=strstr(bp, "\\n"))) {
8239           *bp1++ = '\n';
8240           *bp1++ = ' ';
8241           bp = bp1;
8242         }
8243         bp = bp1 = buffer;
8244
8245 #if 0
8246   /* This is an experimental code for #pragma inline
8247      and is temporarily disabled for 2.5.0 release */
8248         if(asmInlineMap)
8249         {
8250           symbol *sym;
8251           char *s;
8252           char *cbuf;
8253           int cblen;
8254
8255             cbuf = Safe_strdup(buffer);
8256             cblen = strlen(buffer)+1;
8257             memset(cbuf, 0, cblen);
8258
8259             bp = buffer;
8260             bp1 = cbuf;
8261             while(*bp) {
8262               if(*bp != '%')*bp1++ = *bp++;
8263               else {
8264                 int i;
8265
8266                   bp++;
8267                   i = *bp - '0';
8268                   if(i>elementsInSet(asmInlineMap))break;
8269                   
8270                   bp++;
8271                   s = indexSet(asmInlineMap, i);
8272                   DEBUGpc("searching symbol s = `%s'", s);
8273                   sym = findSym(SymbolTab, NULL, s);
8274
8275                   if(sym->reqv) {
8276                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8277                   } else {
8278                     strcat(bp1, sym->rname);
8279                   }
8280                   
8281                   while(*bp1)bp1++;
8282               }
8283               
8284               if(strlen(bp1) > cblen - 16) {
8285                 int i = strlen(cbuf);
8286                 cblen += 50;
8287                 cbuf = realloc(cbuf, cblen);
8288                 memset(cbuf+i, 0, 50);
8289                 bp1 = cbuf + i;
8290               }
8291             }
8292             
8293             free(buffer);
8294             buffer = Safe_strdup( cbuf );
8295             free(cbuf);
8296             
8297             bp = bp1 = buffer;
8298         }
8299 #endif  /* 0 */
8300
8301         /* emit each line as a code */
8302         while (*bp) {
8303                 if (*bp == '\n') {
8304                         *bp++ = '\0';
8305
8306                         if(*bp1)
8307                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8308                         bp1 = bp;
8309                 } else {
8310                         if (*bp == ':') {
8311                                 bp++;
8312                                 *bp = '\0';
8313                                 bp++;
8314
8315                                 /* print label, use this special format with NULL directive
8316                                  * to denote that the argument should not be indented with tab */
8317                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8318                                 bp1 = bp;
8319                         } else
8320                                 bp++;
8321                 }
8322         }
8323
8324         if ((bp1 != bp) && *bp1)
8325                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8326
8327
8328     Safe_free(buffer);
8329
8330     _G.inLine -= (!options.asmpeep);
8331 }
8332
8333 /*-----------------------------------------------------------------*/
8334 /* genRRC - rotate right with carry                                */
8335 /*-----------------------------------------------------------------*/
8336 static void genRRC (iCode *ic)
8337 {
8338   operand *left , *result ;
8339   int size, offset = 0, same;
8340
8341   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8342
8343   /* rotate right with carry */
8344   left = IC_LEFT(ic);
8345   result=IC_RESULT(ic);
8346   pic16_aopOp (left,ic,FALSE);
8347   pic16_aopOp (result,ic,TRUE);
8348
8349   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8350
8351   same = pic16_sameRegs(AOP(result),AOP(left));
8352
8353   size = AOP_SIZE(result);    
8354
8355   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8356
8357   /* get the lsb and put it into the carry */
8358   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8359
8360   offset = 0 ;
8361
8362   while(size--) {
8363
8364     if(same) {
8365       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8366     } else {
8367       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8368       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8369     }
8370
8371     offset++;
8372   }
8373
8374   pic16_freeAsmop(left,NULL,ic,TRUE);
8375   pic16_freeAsmop(result,NULL,ic,TRUE);
8376 }
8377
8378 /*-----------------------------------------------------------------*/
8379 /* genRLC - generate code for rotate left with carry               */
8380 /*-----------------------------------------------------------------*/
8381 static void genRLC (iCode *ic)
8382 {    
8383   operand *left , *result ;
8384   int size, offset = 0;
8385   int same;
8386
8387   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8388   /* rotate right with carry */
8389   left = IC_LEFT(ic);
8390   result=IC_RESULT(ic);
8391   pic16_aopOp (left,ic,FALSE);
8392   pic16_aopOp (result,ic,TRUE);
8393
8394   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8395
8396   same = pic16_sameRegs(AOP(result),AOP(left));
8397
8398   /* move it to the result */
8399   size = AOP_SIZE(result);    
8400
8401   /* get the msb and put it into the carry */
8402   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8403
8404   offset = 0 ;
8405
8406   while(size--) {
8407
8408     if(same) {
8409       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8410     } else {
8411       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8412       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8413     }
8414
8415     offset++;
8416   }
8417
8418
8419   pic16_freeAsmop(left,NULL,ic,TRUE);
8420   pic16_freeAsmop(result,NULL,ic,TRUE);
8421 }
8422
8423
8424 /* gpasm can get the highest order bit with HIGH/UPPER
8425  * so the following probably is not needed -- VR */
8426  
8427 /*-----------------------------------------------------------------*/
8428 /* genGetHbit - generates code get highest order bit               */
8429 /*-----------------------------------------------------------------*/
8430 static void genGetHbit (iCode *ic)
8431 {
8432     operand *left, *result;
8433     left = IC_LEFT(ic);
8434     result=IC_RESULT(ic);
8435     pic16_aopOp (left,ic,FALSE);
8436     pic16_aopOp (result,ic,FALSE);
8437
8438     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8439     /* get the highest order byte into a */
8440     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8441     if(AOP_TYPE(result) == AOP_CRY){
8442         pic16_emitcode("rlc","a");
8443         pic16_outBitC(result);
8444     }
8445     else{
8446         pic16_emitcode("rl","a");
8447         pic16_emitcode("anl","a,#0x01");
8448         pic16_outAcc(result);
8449     }
8450
8451
8452     pic16_freeAsmop(left,NULL,ic,TRUE);
8453     pic16_freeAsmop(result,NULL,ic,TRUE);
8454 }
8455
8456 #if 0
8457 /*-----------------------------------------------------------------*/
8458 /* AccRol - rotate left accumulator by known count                 */
8459 /*-----------------------------------------------------------------*/
8460 static void AccRol (int shCount)
8461 {
8462     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8463     shCount &= 0x0007;              // shCount : 0..7
8464     switch(shCount){
8465         case 0 :
8466             break;
8467         case 1 :
8468             pic16_emitcode("rl","a");
8469             break;
8470         case 2 :
8471             pic16_emitcode("rl","a");
8472             pic16_emitcode("rl","a");
8473             break;
8474         case 3 :
8475             pic16_emitcode("swap","a");
8476             pic16_emitcode("rr","a");
8477             break;
8478         case 4 :
8479             pic16_emitcode("swap","a");
8480             break;
8481         case 5 :
8482             pic16_emitcode("swap","a");
8483             pic16_emitcode("rl","a");
8484             break;
8485         case 6 :
8486             pic16_emitcode("rr","a");
8487             pic16_emitcode("rr","a");
8488             break;
8489         case 7 :
8490             pic16_emitcode("rr","a");
8491             break;
8492     }
8493 }
8494 #endif
8495
8496 /*-----------------------------------------------------------------*/
8497 /* AccLsh - left shift accumulator by known count                  */
8498 /*-----------------------------------------------------------------*/
8499 static void AccLsh (int shCount)
8500 {
8501         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8502         switch(shCount){
8503                 case 0 :
8504                         return;
8505                         break;
8506                 case 1 :
8507                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8508                         break;
8509                 case 2 :
8510                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8511                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8512                         break;
8513                 case 3 :
8514                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8515                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8516                         break;
8517                 case 4 :
8518                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8519                         break;
8520                 case 5 :
8521                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8522                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8523                         break;
8524                 case 6 :
8525                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8526                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8527                         break;
8528                 case 7 :
8529                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8530                         break;
8531         }
8532
8533         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8534 }
8535
8536 /*-----------------------------------------------------------------*/
8537 /* AccRsh - right shift accumulator by known count                 */
8538 /*-----------------------------------------------------------------*/
8539 static void AccRsh (int shCount, int andmask)
8540 {
8541         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8542         switch(shCount){
8543                 case 0 :
8544                         return; break;
8545                 case 1 :
8546                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8547                         break;
8548                 case 2 :
8549                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8550                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8551                         break;
8552                 case 3 :
8553                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8554                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8555                         break;
8556                 case 4 :
8557                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8558                         break;
8559                 case 5 :
8560                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8561                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8562                         break;
8563                 case 6 :
8564                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8565                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8566                         break;
8567                 case 7 :
8568                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8569                         break;
8570         }
8571         
8572         if(andmask)
8573                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8574         else
8575                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8576 }
8577
8578 #if 0
8579 /*-----------------------------------------------------------------*/
8580 /* AccSRsh - signed right shift accumulator by known count                 */
8581 /*-----------------------------------------------------------------*/
8582 static void AccSRsh (int shCount)
8583 {
8584     symbol *tlbl ;
8585     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8586     if(shCount != 0){
8587         if(shCount == 1){
8588             pic16_emitcode("mov","c,acc.7");
8589             pic16_emitcode("rrc","a");
8590         } else if(shCount == 2){
8591             pic16_emitcode("mov","c,acc.7");
8592             pic16_emitcode("rrc","a");
8593             pic16_emitcode("mov","c,acc.7");
8594             pic16_emitcode("rrc","a");
8595         } else {
8596             tlbl = newiTempLabel(NULL);
8597             /* rotate right accumulator */
8598             AccRol(8 - shCount);
8599             /* and kill the higher order bits */
8600             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8601             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8602             pic16_emitcode("orl","a,#0x%02x",
8603                      (unsigned char)~SRMask[shCount]);
8604             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8605         }
8606     }
8607 }
8608 #endif
8609
8610 /*-----------------------------------------------------------------*/
8611 /* shiftR1Left2Result - shift right one byte from left to result   */
8612 /*-----------------------------------------------------------------*/
8613 static void shiftR1Left2ResultSigned (operand *left, int offl,
8614                                 operand *result, int offr,
8615                                 int shCount)
8616 {
8617   int same;
8618
8619   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8620
8621   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8622
8623   switch(shCount) {
8624   case 1:
8625     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8626     if(same) 
8627       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8628     else {
8629       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8630       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8631     }
8632
8633     break;
8634   case 2:
8635
8636     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8637     if(same) 
8638       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8639     else {
8640       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8641       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8642     }
8643     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8644     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8645
8646     break;
8647
8648   case 3:
8649     if(same)
8650       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8651     else {
8652       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8653       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8654     }
8655
8656     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8657     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8658     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8659
8660     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8661     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8662
8663     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8664     break;
8665
8666   case 4:
8667     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8668     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8669     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8670     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8671     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8672     break;
8673   case 5:
8674     if(same) {
8675       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8676     } else {
8677       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8678       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8679     }
8680     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8681     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8682     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8683     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8684     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8685     break;
8686
8687   case 6:
8688     if(same) {
8689       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8690       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8691       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8692       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8693       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8694       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8695     } else {
8696       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8697       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8698       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8699       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8700       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8701     }
8702     break;
8703
8704   case 7:
8705     if(same) {
8706       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8707       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8708       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8709       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8710     } else {
8711       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8712       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8713       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8714     }
8715
8716   default:
8717     break;
8718   }
8719 }
8720
8721 /*-----------------------------------------------------------------*/
8722 /* shiftR1Left2Result - shift right one byte from left to result   */
8723 /*-----------------------------------------------------------------*/
8724 static void shiftR1Left2Result (operand *left, int offl,
8725                                 operand *result, int offr,
8726                                 int shCount, int sign)
8727 {
8728   int same;
8729
8730   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8731
8732   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8733
8734   /* Copy the msb into the carry if signed. */
8735   if(sign) {
8736     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8737     return;
8738   }
8739
8740
8741
8742   switch(shCount) {
8743   case 1:
8744     emitCLRC;
8745     if(same) 
8746       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8747     else {
8748       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8749       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8750     }
8751     break;
8752   case 2:
8753     emitCLRC;
8754     if(same) {
8755       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8756     } else {
8757       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8758       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8759     }
8760     emitCLRC;
8761     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8762
8763     break;
8764   case 3:
8765     if(same)
8766       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8767     else {
8768       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8769       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8770     }
8771
8772     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8773     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8774     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8775     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8776     break;
8777       
8778   case 4:
8779     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8780     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8781     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8782     break;
8783
8784   case 5:
8785     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8786     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8787     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8788     //emitCLRC;
8789     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8790
8791     break;
8792   case 6:
8793
8794     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8795     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8796     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8797     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8798     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8799     break;
8800
8801   case 7:
8802
8803     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8804     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8805     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8806
8807     break;
8808
8809   default:
8810     break;
8811   }
8812 }
8813
8814 /*-----------------------------------------------------------------*/
8815 /* shiftL1Left2Result - shift left one byte from left to result    */
8816 /*-----------------------------------------------------------------*/
8817 static void shiftL1Left2Result (operand *left, int offl,
8818                                 operand *result, int offr, int shCount)
8819 {
8820   int same;
8821
8822   //    char *l;
8823   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8824
8825   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8826   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8827     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8828     //    MOVA(l);
8829     /* shift left accumulator */
8830     //AccLsh(shCount); // don't comment out just yet...
8831   //    pic16_aopPut(AOP(result),"a",offr);
8832
8833   switch(shCount) {
8834   case 1:
8835     /* Shift left 1 bit position */
8836     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8837     if(same) {
8838       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8839     } else {
8840       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8841       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8842     }
8843     break;
8844   case 2:
8845     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8846     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8847     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8848     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8849     break;
8850   case 3:
8851     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8852     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8853     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8854     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8855     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8856     break;
8857   case 4:
8858     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8859     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8860     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8861     break;
8862   case 5:
8863     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8864     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8865     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8866     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8867     break;
8868   case 6:
8869     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8870     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8871     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8872     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8873     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8874     break;
8875   case 7:
8876     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8877     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8878     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8879     break;
8880
8881   default:
8882     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8883   }
8884
8885 }
8886
8887 /*-----------------------------------------------------------------*/
8888 /* movLeft2Result - move byte from left to result                  */
8889 /*-----------------------------------------------------------------*/
8890 static void movLeft2Result (operand *left, int offl,
8891                             operand *result, int offr)
8892 {
8893   char *l;
8894   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8895   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8896     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8897
8898     if (*l == '@' && (IS_AOP_PREG(result))) {
8899       pic16_emitcode("mov","a,%s",l);
8900       pic16_aopPut(AOP(result),"a",offr);
8901     } else {
8902       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8903       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8904     }
8905   }
8906 }
8907
8908 /*-----------------------------------------------------------------*/
8909 /* shiftL2Left2Result - shift left two bytes from left to result   */
8910 /*-----------------------------------------------------------------*/
8911 static void shiftL2Left2Result (operand *left, int offl,
8912                                 operand *result, int offr, int shCount)
8913 {
8914   int same = pic16_sameRegs(AOP(result), AOP(left));
8915   int i;
8916
8917   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8918
8919   if (same && (offl != offr)) { // shift bytes
8920     if (offr > offl) {
8921        for(i=1;i>-1;i--) {
8922          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8923          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8924        }
8925     } else { // just treat as different later on
8926                 same = 0;
8927     }
8928   }
8929
8930   if(same) {
8931     switch(shCount) {
8932     case 0:
8933       break;
8934     case 1:
8935     case 2:
8936     case 3:
8937
8938       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8939       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8940       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8941
8942       while(--shCount) {
8943                 emitCLRC;
8944                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8945                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8946       }
8947
8948       break;
8949     case 4:
8950     case 5:
8951       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8952       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8953       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8954       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8955       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8956       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8957       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8958       if(shCount >=5) {
8959                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8960                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8961       }
8962       break;
8963     case 6:
8964       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8965       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8966       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8967       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8968       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8969       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8970       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8971       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8972       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8973       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8974       break;
8975     case 7:
8976       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8977       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8978       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8979       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8980       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8981     }
8982
8983   } else {
8984     switch(shCount) {
8985     case 0:
8986       break;
8987     case 1:
8988     case 2:
8989     case 3:
8990       /* note, use a mov/add for the shift since the mov has a
8991          chance of getting optimized out */
8992       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8993       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8994       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8995       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8996       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8997
8998       while(--shCount) {
8999                 emitCLRC;
9000                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9001                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9002       }
9003       break;
9004
9005     case 4:
9006     case 5:
9007       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9008       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9009       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9010       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9011       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9012       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9013       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9014       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9015
9016
9017       if(shCount == 5) {
9018                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9019                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9020       }
9021       break;
9022     case 6:
9023       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9024       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9025       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9026       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9027
9028       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9029       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9030       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9031       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9032       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9033       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9034       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9035       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9036       break;
9037     case 7:
9038       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9039       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9040       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9041       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9042       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9043     }
9044   }
9045
9046 }
9047 /*-----------------------------------------------------------------*/
9048 /* shiftR2Left2Result - shift right two bytes from left to result  */
9049 /*-----------------------------------------------------------------*/
9050 static void shiftR2Left2Result (operand *left, int offl,
9051                                 operand *result, int offr,
9052                                 int shCount, int sign)
9053 {
9054   int same = pic16_sameRegs(AOP(result), AOP(left));
9055   int i;
9056   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9057
9058   if (same && (offl != offr)) { // shift right bytes
9059     if (offr < offl) {
9060        for(i=0;i<2;i++) {
9061          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9062          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9063        }
9064     } else { // just treat as different later on
9065                 same = 0;
9066     }
9067   }
9068
9069   switch(shCount) {
9070   case 0:
9071     break;
9072   case 1:
9073   case 2:
9074   case 3:
9075     if(sign)
9076       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9077     else
9078       emitCLRC;
9079
9080     if(same) {
9081       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9082       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9083     } else {
9084       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9085       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9086       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9087       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9088     }
9089
9090     while(--shCount) {
9091       if(sign)
9092                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9093       else
9094                 emitCLRC;
9095       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9096       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9097     }
9098     break;
9099   case 4:
9100   case 5:
9101     if(same) {
9102
9103       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9104       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9105       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9106
9107       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9108       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9109       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9110       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9111     } else {
9112       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9113       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9114       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9115
9116       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9117       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9118       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9119       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9120       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9121     }
9122
9123     if(shCount >=5) {
9124       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9125       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9126     }
9127
9128     if(sign) {
9129       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9130       pic16_emitpcode(POC_BTFSC, 
9131                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9132       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9133     }
9134
9135     break;
9136
9137   case 6:
9138     if(same) {
9139
9140       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9141       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9142
9143       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9144       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9145       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9146       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9147       if(sign) {
9148         pic16_emitpcode(POC_BTFSC, 
9149                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9150         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9151       }
9152       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9153       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9154       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9155       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9156     } else {
9157       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9158       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9159       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9160       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9161       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9162       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9163       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9164       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9165       if(sign) {
9166         pic16_emitpcode(POC_BTFSC, 
9167                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9168         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9169       }
9170       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9171       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9172
9173         
9174     }
9175
9176     break;
9177   case 7:
9178     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9179     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9180     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9181     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9182     if(sign) {
9183       emitSKPNC;
9184       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9185     } else 
9186       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9187   }
9188 }
9189
9190
9191 /*-----------------------------------------------------------------*/
9192 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9193 /*-----------------------------------------------------------------*/
9194 static void shiftLLeftOrResult (operand *left, int offl,
9195                                 operand *result, int offr, int shCount)
9196 {
9197     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9198
9199     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9200     /* shift left accumulator */
9201     AccLsh(shCount);
9202     /* or with result */
9203     /* back to result */
9204     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9205 }
9206
9207 /*-----------------------------------------------------------------*/
9208 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9209 /*-----------------------------------------------------------------*/
9210 static void shiftRLeftOrResult (operand *left, int offl,
9211                                 operand *result, int offr, int shCount)
9212 {
9213     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9214     
9215     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9216     /* shift right accumulator */
9217     AccRsh(shCount, 1);
9218     /* or with result */
9219     /* back to result */
9220     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9221 }
9222
9223 /*-----------------------------------------------------------------*/
9224 /* genlshOne - left shift a one byte quantity by known count       */
9225 /*-----------------------------------------------------------------*/
9226 static void genlshOne (operand *result, operand *left, int shCount)
9227 {       
9228     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9229     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9230 }
9231
9232 /*-----------------------------------------------------------------*/
9233 /* genlshTwo - left shift two bytes by known amount != 0           */
9234 /*-----------------------------------------------------------------*/
9235 static void genlshTwo (operand *result,operand *left, int shCount)
9236 {
9237     int size;
9238     
9239     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9240     size = pic16_getDataSize(result);
9241
9242     /* if shCount >= 8 */
9243     if (shCount >= 8) {
9244         shCount -= 8 ;
9245
9246         if (size > 1){
9247             if (shCount)
9248                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9249             else 
9250                 movLeft2Result(left, LSB, result, MSB16);
9251         }
9252         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9253     }
9254
9255     /*  1 <= shCount <= 7 */
9256     else {  
9257         if(size == 1)
9258             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9259         else 
9260             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9261     }
9262 }
9263
9264 /*-----------------------------------------------------------------*/
9265 /* shiftLLong - shift left one long from left to result            */
9266 /* offr = LSB or MSB16                                             */
9267 /*-----------------------------------------------------------------*/
9268 static void shiftLLong (operand *left, operand *result, int offr )
9269 {
9270     int size = AOP_SIZE(result);
9271     int same = pic16_sameRegs(AOP(left),AOP(result));
9272         int i;
9273
9274     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9275
9276         if (same && (offr == MSB16)) { //shift one byte
9277                 for(i=size-1;i>=MSB16;i--) {
9278                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9279                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9280                 }
9281         } else {
9282                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9283         }
9284         
9285     if (size > LSB+offr ){
9286                 if (same) {
9287                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9288                 } else {
9289                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9290                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9291                 }
9292          }
9293
9294     if(size > MSB16+offr){
9295                 if (same) {
9296                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9297                 } else {
9298                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9299                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9300                 }
9301     }
9302
9303     if(size > MSB24+offr){
9304                 if (same) {
9305                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9306                 } else {
9307                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9308                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9309                 }
9310     }
9311
9312     if(size > MSB32+offr){
9313                 if (same) {
9314                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9315                 } else {
9316                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9317                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9318                 }
9319     }
9320     if(offr != LSB)
9321                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9322
9323 }
9324
9325 /*-----------------------------------------------------------------*/
9326 /* genlshFour - shift four byte by a known amount != 0             */
9327 /*-----------------------------------------------------------------*/
9328 static void genlshFour (operand *result, operand *left, int shCount)
9329 {
9330     int size;
9331
9332     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9333     size = AOP_SIZE(result);
9334
9335     /* if shifting more that 3 bytes */
9336     if (shCount >= 24 ) {
9337         shCount -= 24;
9338         if (shCount)
9339             /* lowest order of left goes to the highest
9340             order of the destination */
9341             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9342         else
9343             movLeft2Result(left, LSB, result, MSB32);
9344
9345                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9346                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9347                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9348
9349         return;
9350     }
9351
9352     /* more than two bytes */
9353     else if ( shCount >= 16 ) {
9354         /* lower order two bytes goes to higher order two bytes */
9355         shCount -= 16;
9356         /* if some more remaining */
9357         if (shCount)
9358             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9359         else {
9360             movLeft2Result(left, MSB16, result, MSB32);
9361             movLeft2Result(left, LSB, result, MSB24);
9362         }
9363                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9364                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9365         return;
9366     }    
9367
9368     /* if more than 1 byte */
9369     else if ( shCount >= 8 ) {
9370         /* lower order three bytes goes to higher order  three bytes */
9371         shCount -= 8;
9372         if(size == 2){
9373             if(shCount)
9374                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9375             else
9376                 movLeft2Result(left, LSB, result, MSB16);
9377         }
9378         else{   /* size = 4 */
9379             if(shCount == 0){
9380                 movLeft2Result(left, MSB24, result, MSB32);
9381                 movLeft2Result(left, MSB16, result, MSB24);
9382                 movLeft2Result(left, LSB, result, MSB16);
9383                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9384             }
9385             else if(shCount == 1)
9386                 shiftLLong(left, result, MSB16);
9387             else{
9388                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9389                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9390                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9391                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9392             }
9393         }
9394     }
9395
9396     /* 1 <= shCount <= 7 */
9397     else if(shCount <= 3)
9398     { 
9399         shiftLLong(left, result, LSB);
9400         while(--shCount >= 1)
9401             shiftLLong(result, result, LSB);
9402     }
9403     /* 3 <= shCount <= 7, optimize */
9404     else{
9405         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9406         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9407         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9408     }
9409 }
9410
9411 /*-----------------------------------------------------------------*/
9412 /* genLeftShiftLiteral - left shifting by known count              */
9413 /*-----------------------------------------------------------------*/
9414 void pic16_genLeftShiftLiteral (operand *left,
9415                                  operand *right,
9416                                  operand *result,
9417                                  iCode *ic)
9418 {    
9419     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9420     int size;
9421
9422     FENTRY;
9423     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9424     pic16_freeAsmop(right,NULL,ic,TRUE);
9425
9426     pic16_aopOp(left,ic,FALSE);
9427     pic16_aopOp(result,ic,TRUE);
9428
9429     size = getSize(operandType(result));
9430
9431 #if VIEW_SIZE
9432     pic16_emitcode("; shift left ","result %d, left %d",size,
9433              AOP_SIZE(left));
9434 #endif
9435
9436     /* I suppose that the left size >= result size */
9437     if(shCount == 0){
9438         while(size--){
9439             movLeft2Result(left, size, result, size);
9440         }
9441     }
9442
9443     else if(shCount >= (size * 8))
9444         while(size--)
9445             pic16_aopPut(AOP(result),zero,size);
9446     else{
9447         switch (size) {
9448             case 1:
9449                 genlshOne (result,left,shCount);
9450                 break;
9451
9452             case 2:
9453             case 3:
9454                 genlshTwo (result,left,shCount);
9455                 break;
9456
9457             case 4:
9458                 genlshFour (result,left,shCount);
9459                 break;
9460         }
9461     }
9462     pic16_freeAsmop(left,NULL,ic,TRUE);
9463     pic16_freeAsmop(result,NULL,ic,TRUE);
9464 }
9465
9466 /*-----------------------------------------------------------------*
9467  * genMultiAsm - repeat assembly instruction for size of register.
9468  * if endian == 1, then the high byte (i.e base address + size of 
9469  * register) is used first else the low byte is used first;
9470  *-----------------------------------------------------------------*/
9471 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9472 {
9473
9474   int offset = 0;
9475
9476   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9477
9478   if(!reg)
9479     return;
9480
9481   if(!endian) {
9482     endian = 1;
9483   } else {
9484     endian = -1;
9485     offset = size-1;
9486   }
9487
9488   while(size--) {
9489     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9490     offset += endian;
9491   }
9492
9493 }
9494
9495 #if !(USE_GENERIC_SIGNED_SHIFT)
9496 /*-----------------------------------------------------------------*/
9497 /* genLeftShift - generates code for left shifting                 */
9498 /*-----------------------------------------------------------------*/
9499 static void genLeftShift (iCode *ic)
9500 {
9501   operand *left,*right, *result;
9502   int size, offset;
9503 //  char *l;
9504   symbol *tlbl , *tlbl1;
9505   pCodeOp *pctemp;
9506
9507   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9508
9509   right = IC_RIGHT(ic);
9510   left  = IC_LEFT(ic);
9511   result = IC_RESULT(ic);
9512
9513   pic16_aopOp(right,ic,FALSE);
9514
9515   /* if the shift count is known then do it 
9516      as efficiently as possible */
9517   if (AOP_TYPE(right) == AOP_LIT) {
9518     pic16_genLeftShiftLiteral (left,right,result,ic);
9519     return ;
9520   }
9521
9522   /* shift count is unknown then we have to form
9523    * a loop. Get the loop count in WREG : Note: we take
9524    * only the lower order byte since shifting
9525    * more than 32 bits make no sense anyway, ( the
9526    * largest size of an object can be only 32 bits ) */
9527   
9528   pic16_aopOp(left,ic,FALSE);
9529   pic16_aopOp(result,ic,FALSE);
9530
9531   /* now move the left to the result if they are not the
9532    * same, and if size > 1,
9533    * and if right is not same to result (!!!) -- VR */
9534   if (!pic16_sameRegs(AOP(left),AOP(result))
9535       && (AOP_SIZE(result) > 1)) {
9536
9537     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9538
9539     size = AOP_SIZE(result);
9540     offset=0;
9541     while (size--) {
9542
9543 #if 0
9544       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9545       if (*l == '@' && (IS_AOP_PREG(result))) {
9546
9547           pic16_emitcode("mov","a,%s",l);
9548           pic16_aopPut(AOP(result),"a",offset);
9549       } else
9550 #endif
9551       {
9552         /* we don't know if left is a literal or a register, take care -- VR */
9553         mov2f(AOP(result), AOP(left), offset);
9554       }
9555       offset++;
9556     }
9557   }
9558
9559   size = AOP_SIZE(result);
9560
9561   /* if it is only one byte then */
9562   if (size == 1) {
9563     if(optimized_for_speed) {
9564       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9565       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9566       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9567       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9568       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9569       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9570       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9571       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9572       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9573       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9574       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9575       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9576     } else {
9577
9578       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9579
9580       tlbl = newiTempLabel(NULL);
9581
9582 #if 1
9583       /* this is already done, why change it? */
9584       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9585                 mov2f(AOP(result), AOP(left), 0);
9586       }
9587 #endif
9588
9589       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9590       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9591       pic16_emitpLabel(tlbl->key);
9592       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9593       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9594       emitSKPC;
9595       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9596     }
9597     goto release ;
9598   }
9599     
9600   if (pic16_sameRegs(AOP(left),AOP(result))) {
9601
9602     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9603     
9604     tlbl = newiTempLabel(NULL);
9605     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9606     genMultiAsm(POC_RRCF, result, size,1);
9607     pic16_emitpLabel(tlbl->key);
9608     genMultiAsm(POC_RLCF, result, size,0);
9609     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9610     emitSKPC;
9611     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9612     goto release;
9613   }
9614
9615   //tlbl = newiTempLabel(NULL);
9616   //offset = 0 ;   
9617   //tlbl1 = newiTempLabel(NULL);
9618
9619   //reAdjustPreg(AOP(result));    
9620     
9621   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9622   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9623   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9624   //MOVA(l);
9625   //pic16_emitcode("add","a,acc");         
9626   //pic16_aopPut(AOP(result),"a",offset++);
9627   //while (--size) {
9628   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9629   //  MOVA(l);
9630   //  pic16_emitcode("rlc","a");         
9631   //  pic16_aopPut(AOP(result),"a",offset++);
9632   //}
9633   //reAdjustPreg(AOP(result));
9634
9635   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9636   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9637
9638
9639   tlbl = newiTempLabel(NULL);
9640   tlbl1= newiTempLabel(NULL);
9641
9642   size = AOP_SIZE(result);
9643   offset = 1;
9644
9645   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9646
9647   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9648
9649   /* offset should be 0, 1 or 3 */
9650   
9651   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9652   emitSKPNZ;
9653   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9654
9655   pic16_emitpcode(POC_MOVWF, pctemp);
9656
9657
9658   pic16_emitpLabel(tlbl->key);
9659
9660   emitCLRC;
9661   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9662   while(--size)
9663     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9664
9665   pic16_emitpcode(POC_DECFSZ,  pctemp);
9666   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9667   pic16_emitpLabel(tlbl1->key);
9668
9669   pic16_popReleaseTempReg(pctemp,1);
9670
9671
9672  release:
9673   pic16_freeAsmop (right,NULL,ic,TRUE);
9674   pic16_freeAsmop(left,NULL,ic,TRUE);
9675   pic16_freeAsmop(result,NULL,ic,TRUE);
9676 }
9677 #endif
9678
9679
9680 #if 0
9681 #error old code (left here for reference)
9682 /*-----------------------------------------------------------------*/
9683 /* genLeftShift - generates code for left shifting                 */
9684 /*-----------------------------------------------------------------*/
9685 static void genLeftShift (iCode *ic)
9686 {
9687   operand *left,*right, *result;
9688   int size, offset;
9689   char *l;
9690   symbol *tlbl , *tlbl1;
9691   pCodeOp *pctemp;
9692
9693   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9694
9695   right = IC_RIGHT(ic);
9696   left  = IC_LEFT(ic);
9697   result = IC_RESULT(ic);
9698
9699   pic16_aopOp(right,ic,FALSE);
9700
9701   /* if the shift count is known then do it 
9702      as efficiently as possible */
9703   if (AOP_TYPE(right) == AOP_LIT) {
9704     pic16_genLeftShiftLiteral (left,right,result,ic);
9705     return ;
9706   }
9707
9708   /* shift count is unknown then we have to form 
9709      a loop get the loop count in B : Note: we take
9710      only the lower order byte since shifting
9711      more that 32 bits make no sense anyway, ( the
9712      largest size of an object can be only 32 bits ) */  
9713
9714     
9715   pic16_aopOp(left,ic,FALSE);
9716   pic16_aopOp(result,ic,FALSE);
9717
9718   /* now move the left to the result if they are not the
9719      same */
9720   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9721       AOP_SIZE(result) > 1) {
9722
9723     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9724
9725     size = AOP_SIZE(result);
9726     offset=0;
9727     while (size--) {
9728       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9729       if (*l == '@' && (IS_AOP_PREG(result))) {
9730
9731         pic16_emitcode("mov","a,%s",l);
9732         pic16_aopPut(AOP(result),"a",offset);
9733       } else {
9734
9735         /* we don't know if left is a literal or a register, take care -- VR */
9736         mov2f(AOP(result), AOP(left), offset);
9737       }
9738       offset++;
9739     }
9740   }
9741
9742   size = AOP_SIZE(result);
9743
9744   /* if it is only one byte then */
9745   if (size == 1) {
9746     if(optimized_for_speed) {
9747       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9748       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9749       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9750       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9751       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9752       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9753       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9754       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9755       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9756       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9757       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9758       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9759     } else {
9760
9761       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9762
9763       tlbl = newiTempLabel(NULL);
9764       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9765                 mov2f(AOP(result), AOP(left), 0);
9766                 
9767 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9768 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9769       }
9770
9771       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9772       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9773       pic16_emitpLabel(tlbl->key);
9774       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9775       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9776       emitSKPC;
9777       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9778     }
9779     goto release ;
9780   }
9781     
9782   if (pic16_sameRegs(AOP(left),AOP(result))) {
9783
9784     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9785     
9786     tlbl = newiTempLabel(NULL);
9787     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9788     genMultiAsm(POC_RRCF, result, size,1);
9789     pic16_emitpLabel(tlbl->key);
9790     genMultiAsm(POC_RLCF, result, size,0);
9791     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9792     emitSKPC;
9793     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9794     goto release;
9795   }
9796
9797   //tlbl = newiTempLabel(NULL);
9798   //offset = 0 ;   
9799   //tlbl1 = newiTempLabel(NULL);
9800
9801   //reAdjustPreg(AOP(result));    
9802     
9803   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9804   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9805   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9806   //MOVA(l);
9807   //pic16_emitcode("add","a,acc");         
9808   //pic16_aopPut(AOP(result),"a",offset++);
9809   //while (--size) {
9810   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9811   //  MOVA(l);
9812   //  pic16_emitcode("rlc","a");         
9813   //  pic16_aopPut(AOP(result),"a",offset++);
9814   //}
9815   //reAdjustPreg(AOP(result));
9816
9817   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9818   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9819
9820
9821   tlbl = newiTempLabel(NULL);
9822   tlbl1= newiTempLabel(NULL);
9823
9824   size = AOP_SIZE(result);
9825   offset = 1;
9826
9827   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9828
9829   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9830
9831   /* offset should be 0, 1 or 3 */
9832   
9833   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9834   emitSKPNZ;
9835   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9836
9837   pic16_emitpcode(POC_MOVWF, pctemp);
9838
9839
9840   pic16_emitpLabel(tlbl->key);
9841
9842   emitCLRC;
9843   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9844   while(--size)
9845     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9846
9847   pic16_emitpcode(POC_DECFSZ,  pctemp);
9848   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9849   pic16_emitpLabel(tlbl1->key);
9850
9851   pic16_popReleaseTempReg(pctemp,1);
9852
9853
9854  release:
9855   pic16_freeAsmop (right,NULL,ic,TRUE);
9856   pic16_freeAsmop(left,NULL,ic,TRUE);
9857   pic16_freeAsmop(result,NULL,ic,TRUE);
9858 }
9859 #endif
9860
9861 /*-----------------------------------------------------------------*/
9862 /* genrshOne - right shift a one byte quantity by known count      */
9863 /*-----------------------------------------------------------------*/
9864 static void genrshOne (operand *result, operand *left,
9865                        int shCount, int sign)
9866 {
9867     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9868     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9869 }
9870
9871 /*-----------------------------------------------------------------*/
9872 /* genrshTwo - right shift two bytes by known amount != 0          */
9873 /*-----------------------------------------------------------------*/
9874 static void genrshTwo (operand *result,operand *left,
9875                        int shCount, int sign)
9876 {
9877   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9878   /* if shCount >= 8 */
9879   if (shCount >= 8) {
9880     shCount -= 8 ;
9881     if (shCount)
9882       shiftR1Left2Result(left, MSB16, result, LSB,
9883                          shCount, sign);
9884     else
9885       movLeft2Result(left, MSB16, result, LSB);
9886
9887     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9888
9889     if(sign) {
9890       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9891       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
9892     }
9893   }
9894
9895   /*  1 <= shCount <= 7 */
9896   else
9897     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9898 }
9899
9900 /*-----------------------------------------------------------------*/
9901 /* shiftRLong - shift right one long from left to result           */
9902 /* offl = LSB or MSB16                                             */
9903 /*-----------------------------------------------------------------*/
9904 static void shiftRLong (operand *left, int offl,
9905                         operand *result, int sign)
9906 {
9907     int size = AOP_SIZE(result);
9908     int same = pic16_sameRegs(AOP(left),AOP(result));
9909     int i;
9910     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9911
9912         if (same && (offl == MSB16)) { //shift one byte right
9913                 for(i=MSB16;i<size;i++) {
9914                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9915                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9916                 }
9917         }
9918
9919     if(sign)
9920                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9921         else
9922                 emitCLRC;
9923
9924         if (same) {
9925                 if (offl == LSB)
9926                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9927         } else {
9928         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9929         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9930         }
9931
9932     if(offl == MSB16) {
9933         /* add sign of "a" */
9934         pic16_addSign(result, MSB32, sign);
9935         }
9936
9937         if (same) {
9938         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9939         } else {
9940         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9941         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9942         }
9943         
9944         if (same) {
9945         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9946         } else {
9947         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9948         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9949         }
9950
9951         if (same) {
9952         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9953         } else {
9954         if(offl == LSB){
9955                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9956                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9957         }
9958         }
9959 }
9960
9961 /*-----------------------------------------------------------------*/
9962 /* genrshFour - shift four byte by a known amount != 0             */
9963 /*-----------------------------------------------------------------*/
9964 static void genrshFour (operand *result, operand *left,
9965                         int shCount, int sign)
9966 {
9967   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9968   /* if shifting more that 3 bytes */
9969   if(shCount >= 24 ) {
9970     shCount -= 24;
9971     if(shCount)
9972       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9973     else
9974       movLeft2Result(left, MSB32, result, LSB);
9975
9976     pic16_addSign(result, MSB16, sign);
9977   }
9978   else if(shCount >= 16){
9979     shCount -= 16;
9980     if(shCount)
9981       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9982     else{
9983       movLeft2Result(left, MSB24, result, LSB);
9984       movLeft2Result(left, MSB32, result, MSB16);
9985     }
9986     pic16_addSign(result, MSB24, sign);
9987   }
9988   else if(shCount >= 8){
9989     shCount -= 8;
9990     if(shCount == 1)
9991       shiftRLong(left, MSB16, result, sign);
9992     else if(shCount == 0){
9993       movLeft2Result(left, MSB16, result, LSB);
9994       movLeft2Result(left, MSB24, result, MSB16);
9995       movLeft2Result(left, MSB32, result, MSB24);
9996       pic16_addSign(result, MSB32, sign);
9997     }
9998     else{ //shcount >= 2
9999       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10000       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10001       /* the last shift is signed */
10002       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10003       pic16_addSign(result, MSB32, sign);
10004     }
10005   }
10006   else{   /* 1 <= shCount <= 7 */
10007     if(shCount <= 2){
10008       shiftRLong(left, LSB, result, sign);
10009       if(shCount == 2)
10010         shiftRLong(result, LSB, result, sign);
10011     }
10012     else{
10013       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10014       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10015       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10016     }
10017   }
10018 }
10019
10020 /*-----------------------------------------------------------------*/
10021 /* genRightShiftLiteral - right shifting by known count            */
10022 /*-----------------------------------------------------------------*/
10023 static void genRightShiftLiteral (operand *left,
10024                                   operand *right,
10025                                   operand *result,
10026                                   iCode *ic,
10027                                   int sign)
10028 {    
10029   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10030   int lsize,res_size;
10031
10032   pic16_freeAsmop(right,NULL,ic,TRUE);
10033
10034   pic16_aopOp(left,ic,FALSE);
10035   pic16_aopOp(result,ic,TRUE);
10036
10037   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10038
10039 #if VIEW_SIZE
10040   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10041                  AOP_SIZE(left));
10042 #endif
10043
10044   lsize = pic16_getDataSize(left);
10045   res_size = pic16_getDataSize(result);
10046   /* test the LEFT size !!! */
10047
10048   /* I suppose that the left size >= result size */
10049   if(shCount == 0){
10050     assert (res_size <= lsize);
10051     while (res_size--) {
10052       mov2f (AOP(result), AOP(left), res_size);
10053     } // for
10054   }
10055
10056   else if(shCount >= (lsize * 8)){
10057
10058     if(res_size == 1) {
10059       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10060       if(sign) {
10061         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10062         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10063       }
10064     } else {
10065
10066       if(sign) {
10067         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10068         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10069         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10070         while(res_size--)
10071           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10072
10073       } else {
10074
10075         while(res_size--)
10076           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10077       }
10078     }
10079   } else {
10080
10081     switch (res_size) {
10082     case 1:
10083       genrshOne (result,left,shCount,sign);
10084       break;
10085
10086     case 2:
10087       genrshTwo (result,left,shCount,sign);
10088       break;
10089
10090     case 4:
10091       genrshFour (result,left,shCount,sign);
10092       break;
10093     default :
10094       break;
10095     }
10096
10097   }
10098
10099   pic16_freeAsmop(left,NULL,ic,TRUE);
10100   pic16_freeAsmop(result,NULL,ic,TRUE);
10101 }
10102
10103 #if !(USE_GENERIC_SIGNED_SHIFT)
10104 /*-----------------------------------------------------------------*/
10105 /* genSignedRightShift - right shift of signed number              */
10106 /*-----------------------------------------------------------------*/
10107 static void genSignedRightShift (iCode *ic)
10108 {
10109   operand *right, *left, *result;
10110   int size, offset;
10111   //  char *l;
10112   symbol *tlbl, *tlbl1 ;
10113   pCodeOp *pctemp;
10114
10115   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10116
10117   /* we do it the hard way put the shift count in b
10118      and loop thru preserving the sign */
10119   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10120
10121   right = IC_RIGHT(ic);
10122   left  = IC_LEFT(ic);
10123   result = IC_RESULT(ic);
10124
10125   pic16_aopOp(right,ic,FALSE);  
10126   pic16_aopOp(left,ic,FALSE);
10127   pic16_aopOp(result,ic,FALSE);
10128
10129
10130   if ( AOP_TYPE(right) == AOP_LIT) {
10131     genRightShiftLiteral (left,right,result,ic,1);
10132     return ;
10133   }
10134   /* shift count is unknown then we have to form 
10135      a loop get the loop count in B : Note: we take
10136      only the lower order byte since shifting
10137      more that 32 bits make no sense anyway, ( the
10138      largest size of an object can be only 32 bits ) */  
10139
10140   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10141   //pic16_emitcode("inc","b");
10142   //pic16_freeAsmop (right,NULL,ic,TRUE);
10143   //pic16_aopOp(left,ic,FALSE);
10144   //pic16_aopOp(result,ic,FALSE);
10145
10146   /* now move the left to the result if they are not the
10147      same */
10148   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10149       AOP_SIZE(result) > 1) {
10150
10151     size = AOP_SIZE(result);
10152     offset=0;
10153     while (size--) { 
10154       /*
10155         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10156         if (*l == '@' && IS_AOP_PREG(result)) {
10157
10158         pic16_emitcode("mov","a,%s",l);
10159         pic16_aopPut(AOP(result),"a",offset);
10160         } else
10161         pic16_aopPut(AOP(result),l,offset);
10162       */
10163       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10164       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10165
10166       offset++;
10167     }
10168   }
10169
10170   /* mov the highest order bit to OVR */    
10171   tlbl = newiTempLabel(NULL);
10172   tlbl1= newiTempLabel(NULL);
10173
10174   size = AOP_SIZE(result);
10175   offset = size - 1;
10176
10177   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10178
10179   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10180
10181   /* offset should be 0, 1 or 3 */
10182   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10183   emitSKPNZ;
10184   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10185
10186   pic16_emitpcode(POC_MOVWF, pctemp);
10187
10188
10189   pic16_emitpLabel(tlbl->key);
10190
10191   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10192   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10193
10194   while(--size) {
10195     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10196   }
10197
10198   pic16_emitpcode(POC_DECFSZ,  pctemp);
10199   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10200   pic16_emitpLabel(tlbl1->key);
10201
10202   pic16_popReleaseTempReg(pctemp,1);
10203 #if 0
10204   size = AOP_SIZE(result);
10205   offset = size - 1;
10206   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10207   pic16_emitcode("rlc","a");
10208   pic16_emitcode("mov","ov,c");
10209   /* if it is only one byte then */
10210   if (size == 1) {
10211     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10212     MOVA(l);
10213     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10214     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10215     pic16_emitcode("mov","c,ov");
10216     pic16_emitcode("rrc","a");
10217     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10218     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10219     pic16_aopPut(AOP(result),"a",0);
10220     goto release ;
10221   }
10222
10223   reAdjustPreg(AOP(result));
10224   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10225   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10226   pic16_emitcode("mov","c,ov");
10227   while (size--) {
10228     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10229     MOVA(l);
10230     pic16_emitcode("rrc","a");         
10231     pic16_aopPut(AOP(result),"a",offset--);
10232   }
10233   reAdjustPreg(AOP(result));
10234   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10235   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10236
10237  release:
10238 #endif
10239
10240   pic16_freeAsmop(left,NULL,ic,TRUE);
10241   pic16_freeAsmop(result,NULL,ic,TRUE);
10242   pic16_freeAsmop(right,NULL,ic,TRUE);
10243 }
10244 #endif
10245
10246 #if !(USE_GENERIC_SIGNED_SHIFT)
10247 #warning This implementation of genRightShift() is incomplete!
10248 /*-----------------------------------------------------------------*/
10249 /* genRightShift - generate code for right shifting                */
10250 /*-----------------------------------------------------------------*/
10251 static void genRightShift (iCode *ic)
10252 {
10253     operand *right, *left, *result;
10254     sym_link *letype ;
10255     int size, offset;
10256     char *l;
10257     symbol *tlbl, *tlbl1 ;
10258
10259     /* if signed then we do it the hard way preserve the
10260     sign bit moving it inwards */
10261     letype = getSpec(operandType(IC_LEFT(ic)));
10262     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10263
10264     if (!SPEC_USIGN(letype)) {
10265         genSignedRightShift (ic);
10266         return ;
10267     }
10268
10269     /* signed & unsigned types are treated the same : i.e. the
10270     signed is NOT propagated inwards : quoting from the
10271     ANSI - standard : "for E1 >> E2, is equivalent to division
10272     by 2**E2 if unsigned or if it has a non-negative value,
10273     otherwise the result is implementation defined ", MY definition
10274     is that the sign does not get propagated */
10275
10276     right = IC_RIGHT(ic);
10277     left  = IC_LEFT(ic);
10278     result = IC_RESULT(ic);
10279
10280     pic16_aopOp(right,ic,FALSE);
10281
10282     /* if the shift count is known then do it 
10283     as efficiently as possible */
10284     if (AOP_TYPE(right) == AOP_LIT) {
10285         genRightShiftLiteral (left,right,result,ic, 0);
10286         return ;
10287     }
10288
10289     /* shift count is unknown then we have to form 
10290     a loop get the loop count in B : Note: we take
10291     only the lower order byte since shifting
10292     more that 32 bits make no sense anyway, ( the
10293     largest size of an object can be only 32 bits ) */  
10294
10295     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10296     pic16_emitcode("inc","b");
10297     pic16_aopOp(left,ic,FALSE);
10298     pic16_aopOp(result,ic,FALSE);
10299
10300     /* now move the left to the result if they are not the
10301     same */
10302     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10303         AOP_SIZE(result) > 1) {
10304
10305         size = AOP_SIZE(result);
10306         offset=0;
10307         while (size--) {
10308             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10309             if (*l == '@' && IS_AOP_PREG(result)) {
10310
10311                 pic16_emitcode("mov","a,%s",l);
10312                 pic16_aopPut(AOP(result),"a",offset);
10313             } else
10314                 pic16_aopPut(AOP(result),l,offset);
10315             offset++;
10316         }
10317     }
10318
10319     tlbl = newiTempLabel(NULL);
10320     tlbl1= newiTempLabel(NULL);
10321     size = AOP_SIZE(result);
10322     offset = size - 1;
10323
10324     /* if it is only one byte then */
10325     if (size == 1) {
10326
10327       tlbl = newiTempLabel(NULL);
10328       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10329         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10330         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10331       }
10332
10333       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10334       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10335       pic16_emitpLabel(tlbl->key);
10336       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10337       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10338       emitSKPC;
10339       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10340
10341       goto release ;
10342     }
10343
10344     reAdjustPreg(AOP(result));
10345     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10346     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10347     CLRC;
10348     while (size--) {
10349         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10350         MOVA(l);
10351         pic16_emitcode("rrc","a");         
10352         pic16_aopPut(AOP(result),"a",offset--);
10353     }
10354     reAdjustPreg(AOP(result));
10355
10356     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10357     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10358
10359 release:
10360     pic16_freeAsmop(left,NULL,ic,TRUE);
10361     pic16_freeAsmop (right,NULL,ic,TRUE);
10362     pic16_freeAsmop(result,NULL,ic,TRUE);
10363 }
10364 #endif
10365
10366 #if (USE_GENERIC_SIGNED_SHIFT)
10367 /*-----------------------------------------------------------------*/
10368 /* genGenericShift - generates code for left or right shifting     */
10369 /*-----------------------------------------------------------------*/
10370 static void genGenericShift (iCode *ic, int isShiftLeft) {
10371   operand *left,*right, *result;
10372   int offset;
10373   int sign, signedCount;
10374   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10375   PIC_OPCODE pos_shift, neg_shift;
10376
10377   FENTRY;
10378
10379   right = IC_RIGHT(ic);
10380   left  = IC_LEFT(ic);
10381   result = IC_RESULT(ic);
10382
10383   pic16_aopOp(right,ic,FALSE);
10384   pic16_aopOp(left,ic,FALSE);
10385   pic16_aopOp(result,ic,TRUE);
10386
10387   sign = !SPEC_USIGN(operandType (left));
10388   signedCount = !SPEC_USIGN(operandType (right));
10389
10390   /* if the shift count is known then do it 
10391      as efficiently as possible */
10392   if (AOP_TYPE(right) == AOP_LIT) {
10393     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10394     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10395     // we should modify right->aopu.aop_lit here!
10396     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10397     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10398     if (isShiftLeft)
10399       pic16_genLeftShiftLiteral (left,right,result,ic);
10400     else
10401       genRightShiftLiteral (left,right,result,ic, sign);
10402
10403     goto release;
10404   } // if (right is literal)
10405
10406   /* shift count is unknown then we have to form a loop.
10407    * Note: we take only the lower order byte since shifting
10408    * more than 32 bits make no sense anyway, ( the
10409    * largest size of an object can be only 32 bits )
10410    * Note: we perform arithmetic shifts if the left operand is
10411    * signed and we do an (effective) right shift, i. e. we
10412    * shift in the sign bit from the left. */
10413    
10414   label_complete = newiTempLabel ( NULL );
10415   label_loop_pos = newiTempLabel ( NULL );
10416   label_loop_neg = NULL;
10417   label_negative = NULL;
10418   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10419   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10420
10421   if (signedCount) {
10422     // additional labels needed
10423     label_loop_neg = newiTempLabel ( NULL );
10424     label_negative = newiTempLabel ( NULL );
10425   } // if
10426
10427   // copy source to result -- this will effectively truncate the left operand to the size of result!
10428   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10429   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10430   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10431     mov2f (AOP(result),AOP(left), offset);
10432   } // for
10433
10434   // if result is longer than left, fill with zeros (or sign)
10435   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10436     if (sign && AOP_SIZE(left) > 0) {
10437       // shift signed operand -- fill with sign
10438       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10439       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10440       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10441       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10442         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10443       } // for
10444     } else {
10445       // shift unsigned operand -- fill result with zeros
10446       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10447         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10448       } // for
10449     }
10450   } // if (size mismatch)
10451
10452   pic16_mov2w (AOP(right), 0);
10453   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10454   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10455   
10456 #if 0
10457   // perform a shift by one (shift count is positive)
10458   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10459   // 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])
10460   pic16_emitpLabel (label_loop_pos->key);
10461   emitCLRC;
10462   if (sign && (pos_shift == POC_RRCF)) {
10463     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10464     emitSETC;
10465   } // if
10466   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10467   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10468   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10469 #else
10470   // perform a shift by one (shift count is positive)
10471   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10472   // 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])
10473   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10474   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10475   emitCLRC;
10476   pic16_emitpLabel (label_loop_pos->key);
10477   if (sign && (pos_shift == POC_RRCF)) {
10478     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10479     emitSETC;
10480   } // if
10481   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10482   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10483   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10484   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10485 #endif
10486
10487   if (signedCount) {
10488     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10489
10490     pic16_emitpLabel (label_negative->key);
10491     // perform a shift by -1 (shift count is negative)
10492     // 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)
10493     emitCLRC;
10494     pic16_emitpLabel (label_loop_neg->key);
10495     if (sign && (neg_shift == POC_RRCF)) {
10496       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10497       emitSETC;
10498     } // if
10499     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10500     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10501     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10502     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10503   } // if (signedCount)
10504
10505   pic16_emitpLabel (label_complete->key);
10506
10507 release:
10508   pic16_freeAsmop (right,NULL,ic,TRUE);
10509   pic16_freeAsmop(left,NULL,ic,TRUE);
10510   pic16_freeAsmop(result,NULL,ic,TRUE);
10511 }
10512
10513 static void genLeftShift (iCode *ic) {
10514   genGenericShift (ic, 1);
10515 }
10516
10517 static void genRightShift (iCode *ic) {
10518   genGenericShift (ic, 0);
10519 }
10520 #endif
10521
10522
10523 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10524 void pic16_loadFSR0(operand *op, int lit)
10525 {
10526   if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10527     pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10528   } else {
10529     assert (!OP_SYMBOL(op)->remat);
10530     // set up FSR0 with address of result
10531     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10532     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10533   }
10534 }
10535
10536 /*-----------------------------------------------------------------*/
10537 /* genUnpackBits - generates code for unpacking bits               */
10538 /*-----------------------------------------------------------------*/
10539 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10540 {    
10541   int shCnt ;
10542   int rlen = 0 ;
10543   sym_link *etype, *letype;
10544   int blen=0, bstr=0;
10545   int lbstr;
10546   int offset = 0 ;
10547
10548     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10549     etype = getSpec(operandType(result));
10550     letype = getSpec(operandType(left));
10551     
10552 //    if(IS_BITFIELD(etype)) {
10553       blen = SPEC_BLEN(etype);
10554       bstr = SPEC_BSTR(etype);
10555 //    }
10556
10557     lbstr = SPEC_BSTR( letype );
10558
10559 #if 1
10560     if((blen == 1) && (bstr < 8)) {
10561       /* it is a single bit, so use the appropriate bit instructions */
10562       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10563
10564       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10565       
10566       // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10567       if(OP_SYMBOL(left)->remat && (ptype == POINTER) && (result)) {
10568         /* workaround to reduce the extra lfsr instruction */
10569         pic16_emitpcode(POC_BTFSC,
10570               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10571       } else {
10572         pic16_loadFSR0 (left, 0);
10573         pic16_emitpcode(POC_BTFSC,
10574               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10575       }
10576         
10577       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10578
10579       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10580       return;
10581     }
10582
10583 #endif
10584
10585         /* the following call to pic16_loadFSR0 is temporary until
10586          * optimization to handle single bit assignments is added
10587          * to the function. Until then use the old safe way! -- VR */
10588
10589     if (OP_SYMBOL(left)->remat) {
10590         // access symbol directly
10591         pic16_mov2w (AOP(left), 0);
10592     } else {
10593         pic16_loadFSR0( left, 0 );
10594  
10595         /* read the first byte  */
10596         switch (ptype) {
10597                 case POINTER:
10598                 case IPOINTER:
10599                 case PPOINTER:
10600                 case FPOINTER:
10601                 case GPOINTER:
10602                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10603                         break;
10604                 case CPOINTER:
10605                         pic16_emitcode("clr","a");
10606                         pic16_emitcode("movc","a","@a+dptr");
10607                         assert (0);
10608                         break;
10609         }
10610     }
10611
10612         /* if we have bitdisplacement then it fits   */
10613         /* into this byte completely or if length is */
10614         /* less than a byte                          */
10615         if ((shCnt = SPEC_BSTR(etype)) || 
10616                 (SPEC_BLEN(etype) <= 8))  {
10617
10618                 /* shift right acc */
10619                 AccRsh(shCnt, 0);
10620
10621                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10622                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10623
10624 /* VR -- normally I would use the following, but since we use the hack,
10625  * to avoid the masking from AccRsh, why not mask it right now? */
10626
10627 /*
10628                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10629 */
10630
10631                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10632           return ;
10633         }
10634
10635
10636
10637         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10638         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10639         exit(-1);
10640
10641     /* bit field did not fit in a byte  */
10642     rlen = SPEC_BLEN(etype) - 8;
10643     pic16_aopPut(AOP(result),"a",offset++);
10644
10645     while (1)  {
10646
10647         switch (ptype) {
10648         case POINTER:
10649         case IPOINTER:
10650             pic16_emitcode("inc","%s",rname);
10651             pic16_emitcode("mov","a,@%s",rname);
10652             break;
10653             
10654         case PPOINTER:
10655             pic16_emitcode("inc","%s",rname);
10656             pic16_emitcode("movx","a,@%s",rname);
10657             break;
10658
10659         case FPOINTER:
10660             pic16_emitcode("inc","dptr");
10661             pic16_emitcode("movx","a,@dptr");
10662             break;
10663             
10664         case CPOINTER:
10665             pic16_emitcode("clr","a");
10666             pic16_emitcode("inc","dptr");
10667             pic16_emitcode("movc","a","@a+dptr");
10668             break;
10669             
10670         case GPOINTER:
10671             pic16_emitcode("inc","dptr");
10672             pic16_emitcode("lcall","__gptrget");
10673             break;
10674         }
10675
10676         rlen -= 8;            
10677         /* if we are done */
10678         if ( rlen <= 0 )
10679             break ;
10680         
10681         pic16_aopPut(AOP(result),"a",offset++);
10682                               
10683     }
10684     
10685     if (rlen) {
10686         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10687         pic16_aopPut(AOP(result),"a",offset);          
10688     }
10689     
10690     return ;
10691 }
10692
10693
10694 static void genDataPointerGet(operand *left,
10695                               operand *result,
10696                               iCode *ic)
10697 {
10698   int size, offset = 0, leoffset=0 ;
10699
10700         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10701         pic16_aopOp(result, ic, TRUE);
10702
10703         FENTRY;
10704
10705         size = AOP_SIZE(result);
10706 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10707
10708
10709 #if 0
10710         /* The following tests may save a redudant movff instruction when
10711          * accessing unions */
10712          
10713         /* if they are the same */
10714         if (operandsEqu (left, result)) {
10715                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10716                 goto release;
10717         }
10718 #endif
10719
10720 #if 0
10721         /* if they are the same registers */
10722         if (pic16_sameRegs(AOP(left),AOP(result))) {
10723                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10724                 goto release;
10725         }
10726 #endif
10727
10728 #if 1
10729         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10730                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10731                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10732                 goto release;
10733         }
10734 #endif
10735
10736
10737 #if 0
10738         if ( AOP_TYPE(left) == AOP_PCODE) {
10739                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
10740                                 AOP(left)->aopu.pcop->name,
10741                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
10742                                 PCOR(AOP(left)->aopu.pcop)->instance:
10743                                 PCOI(AOP(left)->aopu.pcop)->offset);
10744         }
10745 #endif
10746
10747         if(AOP(left)->aopu.pcop->type == PO_DIR)
10748                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10749
10750         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10751
10752         while (size--) {
10753                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10754                 
10755 //              pic16_DumpOp("(result)",result);
10756                 if(is_LitAOp(AOP(result))) {
10757                         pic16_mov2w(AOP(left), offset); // patch 8
10758                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10759                 } else {
10760                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10761                                 pic16_popGet(AOP(left), offset), //patch 8
10762                                 pic16_popGet(AOP(result), offset)));
10763                 }
10764
10765                 offset++;
10766                 leoffset++;
10767         }
10768
10769 release:
10770     pic16_freeAsmop(result,NULL,ic,TRUE);
10771 }
10772
10773
10774
10775 /*-----------------------------------------------------------------*/
10776 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10777 /*-----------------------------------------------------------------*/
10778 static void genNearPointerGet (operand *left, 
10779                                operand *result, 
10780                                iCode *ic)
10781 {
10782 //  asmop *aop = NULL;
10783   //regs *preg = NULL ;
10784   sym_link *rtype, *retype;
10785   sym_link *ltype = operandType(left);    
10786
10787     FENTRY;
10788     
10789     rtype = operandType(result);
10790     retype= getSpec(rtype);
10791     
10792     pic16_aopOp(left,ic,FALSE);
10793
10794 //    pic16_DumpOp("(left)",left);
10795 //    pic16_DumpOp("(result)",result);
10796
10797     /* if left is rematerialisable and
10798      * result is not bit variable type and
10799      * the left is pointer to data space i.e
10800      * lower 128 bytes of space */
10801     
10802     if (AOP_TYPE(left) == AOP_PCODE
10803       && !IS_BITFIELD(retype)
10804       && DCL_TYPE(ltype) == POINTER) {
10805
10806         genDataPointerGet (left,result,ic);
10807         pic16_freeAsmop(left, NULL, ic, TRUE);
10808         return ;
10809     }
10810     
10811     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10812     pic16_aopOp (result,ic,TRUE);
10813     
10814     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10815
10816 #if 1
10817     if(IS_BITFIELD( retype )
10818       && (SPEC_BLEN(operandType(result))==1)
10819     ) {
10820       iCode *nextic;
10821       pCodeOp *jop;
10822       int bitstrt, bytestrt;
10823
10824         /* if this is bitfield of size 1, see if we are checking the value
10825          * of a single bit in an if-statement,
10826          * if yes, then don't generate usual code, but execute the
10827          * genIfx directly -- VR */
10828
10829         nextic = ic->next;
10830
10831         /* CHECK: if next iCode is IFX
10832          * and current result operand is nextic's conditional operand
10833          * and current result operand live ranges ends at nextic's key number
10834          */
10835         if((nextic->op == IFX)
10836           && (result == IC_COND(nextic))
10837           && (OP_LIVETO(result) == nextic->seq)
10838           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10839           ) {
10840             /* everything is ok then */
10841             /* find a way to optimize the genIfx iCode */
10842
10843             bytestrt = SPEC_BSTR(operandType(result))/8;
10844             bitstrt = SPEC_BSTR(operandType(result))%8;
10845             
10846             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10847
10848             genIfxpCOpJump(nextic, jop);
10849             
10850             pic16_freeAsmop(left, NULL, ic, TRUE);
10851             pic16_freeAsmop(result, NULL, ic, TRUE);
10852             return;
10853         }
10854     }
10855 #endif
10856
10857
10858     /* if the value is already in a pointer register
10859      * then don't need anything more */
10860     if (1 || !AOP_INPREG(AOP(left))) {  // AOP_INPREG(AOP(left)) is not always correct...
10861       /* otherwise get a free pointer register */
10862       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10863                 
10864       ;
10865     }
10866
10867     /* if bitfield then unpack the bits */
10868     if (IS_BITFIELD(retype)) 
10869       genUnpackBits (result, left, NULL, POINTER);
10870     else {
10871       /* we have can just get the values */
10872       int size = AOP_SIZE(result);
10873       int offset = 0;   
10874         
10875       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10876
10877       pic16_loadFSR0( left, 0 );
10878
10879       while(size--) {
10880         if(size) {
10881           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10882                 pic16_popGet(AOP(result), offset++)));
10883         } else {
10884           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10885                 pic16_popGet(AOP(result), offset++)));
10886         }
10887       }
10888     }
10889
10890 #if 0
10891     /* now some housekeeping stuff */
10892     if (aop) {
10893       /* we had to allocate for this iCode */
10894       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10895       pic16_freeAsmop(NULL,aop,ic,TRUE);
10896     } else { 
10897       /* we did not allocate which means left
10898        * already in a pointer register, then
10899        * if size > 0 && this could be used again
10900        * we have to point it back to where it 
10901        * belongs */
10902       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10903       if (AOP_SIZE(result) > 1
10904         && !OP_SYMBOL(left)->remat
10905         && ( OP_SYMBOL(left)->liveTo > ic->seq
10906             || ic->depth )) {
10907 //        int size = AOP_SIZE(result) - 1;
10908 //        while (size--)
10909 //          pic16_emitcode("dec","%s",rname);
10910         }
10911     }
10912 #endif
10913
10914     /* done */
10915     pic16_freeAsmop(left,NULL,ic,TRUE);
10916     pic16_freeAsmop(result,NULL,ic,TRUE);
10917 }
10918
10919 /*-----------------------------------------------------------------*/
10920 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10921 /*-----------------------------------------------------------------*/
10922 static void genPagedPointerGet (operand *left, 
10923                                operand *result, 
10924                                iCode *ic)
10925 {
10926     asmop *aop = NULL;
10927     regs *preg = NULL ;
10928     char *rname ;
10929     sym_link *rtype, *retype;    
10930
10931     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10932
10933     rtype = operandType(result);
10934     retype= getSpec(rtype);
10935     
10936     pic16_aopOp(left,ic,FALSE);
10937
10938   /* if the value is already in a pointer register
10939        then don't need anything more */
10940     if (!AOP_INPREG(AOP(left))) {
10941         /* otherwise get a free pointer register */
10942         aop = newAsmop(0);
10943         preg = getFreePtr(ic,&aop,FALSE);
10944         pic16_emitcode("mov","%s,%s",
10945                 preg->name,
10946                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10947         rname = preg->name ;
10948     } else
10949         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10950     
10951     pic16_freeAsmop(left,NULL,ic,TRUE);
10952     pic16_aopOp (result,ic,TRUE);
10953
10954     /* if bitfield then unpack the bits */
10955     if (IS_BITFIELD(retype)) 
10956         genUnpackBits (result,left,rname,PPOINTER);
10957     else {
10958         /* we have can just get the values */
10959         int size = AOP_SIZE(result);
10960         int offset = 0 ;        
10961         
10962         while (size--) {
10963             
10964             pic16_emitcode("movx","a,@%s",rname);
10965             pic16_aopPut(AOP(result),"a",offset);
10966             
10967             offset++ ;
10968             
10969             if (size)
10970                 pic16_emitcode("inc","%s",rname);
10971         }
10972     }
10973
10974     /* now some housekeeping stuff */
10975     if (aop) {
10976         /* we had to allocate for this iCode */
10977         pic16_freeAsmop(NULL,aop,ic,TRUE);
10978     } else { 
10979         /* we did not allocate which means left
10980            already in a pointer register, then
10981            if size > 0 && this could be used again
10982            we have to point it back to where it 
10983            belongs */
10984         if (AOP_SIZE(result) > 1 &&
10985             !OP_SYMBOL(left)->remat &&
10986             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10987               ic->depth )) {
10988             int size = AOP_SIZE(result) - 1;
10989             while (size--)
10990                 pic16_emitcode("dec","%s",rname);
10991         }
10992     }
10993
10994     /* done */
10995     pic16_freeAsmop(result,NULL,ic,TRUE);
10996     
10997         
10998 }
10999
11000 /*-----------------------------------------------------------------*/
11001 /* genFarPointerGet - gget value from far space                    */
11002 /*-----------------------------------------------------------------*/
11003 static void genFarPointerGet (operand *left,
11004                               operand *result, iCode *ic)
11005 {
11006     int size, offset ;
11007     sym_link *retype = getSpec(operandType(result));
11008
11009     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11010
11011     pic16_aopOp(left,ic,FALSE);
11012
11013     /* if the operand is already in dptr 
11014     then we do nothing else we move the value to dptr */
11015     if (AOP_TYPE(left) != AOP_STR) {
11016         /* if this is remateriazable */
11017         if (AOP_TYPE(left) == AOP_IMMD)
11018             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11019         else { /* we need to get it byte by byte */
11020             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11021             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11022             if (options.model == MODEL_FLAT24)
11023             {
11024                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11025             }
11026         }
11027     }
11028     /* so dptr know contains the address */
11029     pic16_freeAsmop(left,NULL,ic,TRUE);
11030     pic16_aopOp(result,ic,TRUE);
11031
11032     /* if bit then unpack */
11033     if (IS_BITFIELD(retype)) 
11034         genUnpackBits(result,left,"dptr",FPOINTER);
11035     else {
11036         size = AOP_SIZE(result);
11037         offset = 0 ;
11038
11039         while (size--) {
11040             pic16_emitcode("movx","a,@dptr");
11041             pic16_aopPut(AOP(result),"a",offset++);
11042             if (size)
11043                 pic16_emitcode("inc","dptr");
11044         }
11045     }
11046
11047     pic16_freeAsmop(result,NULL,ic,TRUE);
11048 }
11049
11050 #if 0
11051 /*-----------------------------------------------------------------*/
11052 /* genCodePointerGet - get value from code space                  */
11053 /*-----------------------------------------------------------------*/
11054 static void genCodePointerGet (operand *left,
11055                                 operand *result, iCode *ic)
11056 {
11057     int size, offset ;
11058     sym_link *retype = getSpec(operandType(result));
11059
11060     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11061
11062     pic16_aopOp(left,ic,FALSE);
11063
11064     /* if the operand is already in dptr 
11065     then we do nothing else we move the value to dptr */
11066     if (AOP_TYPE(left) != AOP_STR) {
11067         /* if this is remateriazable */
11068         if (AOP_TYPE(left) == AOP_IMMD)
11069             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11070         else { /* we need to get it byte by byte */
11071             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11072             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11073             if (options.model == MODEL_FLAT24)
11074             {
11075                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11076             }
11077         }
11078     }
11079     /* so dptr know contains the address */
11080     pic16_freeAsmop(left,NULL,ic,TRUE);
11081     pic16_aopOp(result,ic,FALSE);
11082
11083     /* if bit then unpack */
11084     if (IS_BITFIELD(retype)) 
11085         genUnpackBits(result,left,"dptr",CPOINTER);
11086     else {
11087         size = AOP_SIZE(result);
11088         offset = 0 ;
11089
11090         while (size--) {
11091             pic16_emitcode("clr","a");
11092             pic16_emitcode("movc","a,@a+dptr");
11093             pic16_aopPut(AOP(result),"a",offset++);
11094             if (size)
11095                 pic16_emitcode("inc","dptr");
11096         }
11097     }
11098
11099     pic16_freeAsmop(result,NULL,ic,TRUE);
11100 }
11101 #endif
11102
11103 #if 0
11104 /*-----------------------------------------------------------------*/
11105 /* genGenPointerGet - gget value from generic pointer space        */
11106 /*-----------------------------------------------------------------*/
11107 static void genGenPointerGet (operand *left,
11108                               operand *result, iCode *ic)
11109 {
11110   int size, offset, lit;
11111   sym_link *retype = getSpec(operandType(result));
11112
11113         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11114         pic16_aopOp(left,ic,FALSE);
11115         pic16_aopOp(result,ic,FALSE);
11116         size = AOP_SIZE(result);
11117
11118         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11119
11120         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11121
11122                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11123                 // load FSR0 from immediate
11124                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11125
11126 //              pic16_loadFSR0( left );
11127
11128                 offset = 0;
11129                 while(size--) {
11130                         if(size) {
11131                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11132                         } else {
11133                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11134                         }
11135                         offset++;
11136                 }
11137                 goto release;
11138
11139         }
11140         else { /* we need to get it byte by byte */
11141                 // set up FSR0 with address from left
11142                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11143                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11144                 
11145                 offset = 0 ;
11146
11147                 while(size--) {
11148                         if(size) {
11149                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11150                         } else {
11151                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11152                         }
11153                         offset++;
11154                 }
11155                 goto release;
11156         }
11157
11158   /* if bit then unpack */
11159         if (IS_BITFIELD(retype)) 
11160                 genUnpackBits(result,left,"BAD",GPOINTER);
11161
11162         release:
11163         pic16_freeAsmop(left,NULL,ic,TRUE);
11164         pic16_freeAsmop(result,NULL,ic,TRUE);
11165
11166 }
11167 #endif
11168
11169
11170 /*-----------------------------------------------------------------*/
11171 /* genGenPointerGet - gget value from generic pointer space        */
11172 /*-----------------------------------------------------------------*/
11173 static void genGenPointerGet (operand *left,
11174                               operand *result, iCode *ic)
11175 {
11176   int size, offset, lit;
11177   sym_link *retype = getSpec(operandType(result));
11178
11179     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11180     pic16_aopOp(left,ic,FALSE);
11181     pic16_aopOp(result,ic,TRUE);
11182     size = AOP_SIZE(result);
11183
11184     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11185
11186     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11187
11188       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11189       // load FSR0 from immediate
11190       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11191
11192       werror(W_POSSBUG2, __FILE__, __LINE__);
11193
11194       offset = 0;
11195       while(size--) {
11196         if(size) {
11197           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11198         } else {
11199           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11200         }
11201         offset++;
11202       }
11203
11204       goto release;
11205
11206     } else { /* we need to get it byte by byte */
11207
11208       /* set up WREG:PRODL:FSR0L with address from left */
11209       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11210       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11211       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11212       
11213       pic16_callGenericPointerRW(0, size);
11214       
11215       assignResultValue(result, 1);
11216       
11217       goto release;
11218     }
11219
11220   /* if bit then unpack */
11221     if (IS_BITFIELD(retype)) 
11222       genUnpackBits(result,left,"BAD",GPOINTER);
11223
11224 release:
11225   pic16_freeAsmop(left,NULL,ic,TRUE);
11226   pic16_freeAsmop(result,NULL,ic,TRUE);
11227 }
11228
11229 /*-----------------------------------------------------------------*/
11230 /* genConstPointerGet - get value from const generic pointer space */
11231 /*-----------------------------------------------------------------*/
11232 static void genConstPointerGet (operand *left,
11233                                 operand *result, iCode *ic)
11234 {
11235   //sym_link *retype = getSpec(operandType(result));
11236   // symbol *albl = newiTempLabel(NULL);        // patch 15
11237   // symbol *blbl = newiTempLabel(NULL);        //
11238   // PIC_OPCODE poc;                            // patch 15
11239   int size;
11240   int offset = 0;
11241
11242   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11243   pic16_aopOp(left,ic,FALSE);
11244   pic16_aopOp(result,ic,TRUE);
11245   size = AOP_SIZE(result);
11246
11247   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11248
11249   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11250
11251   // set up table pointer
11252   if( (AOP_TYPE(left) == AOP_PCODE) 
11253       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11254           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11255     {
11256       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11257       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11258       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11259       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11260       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11261       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11262   } else {
11263     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11264     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11265     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11266   }
11267
11268   while(size--) {
11269     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11270     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11271     offset++;
11272   }
11273     
11274   pic16_freeAsmop(left,NULL,ic,TRUE);
11275   pic16_freeAsmop(result,NULL,ic,TRUE);
11276 }
11277
11278
11279 /*-----------------------------------------------------------------*/
11280 /* genPointerGet - generate code for pointer get                   */
11281 /*-----------------------------------------------------------------*/
11282 static void genPointerGet (iCode *ic)
11283 {
11284   operand *left, *result ;
11285   sym_link *type, *etype;
11286   int p_type;
11287
11288     FENTRY;
11289     
11290     left = IC_LEFT(ic);
11291     result = IC_RESULT(ic) ;
11292
11293     /* depending on the type of pointer we need to
11294     move it to the correct pointer register */
11295     type = operandType(left);
11296     etype = getSpec(type);
11297
11298 #if 0
11299     if (IS_PTR_CONST(type))
11300 #else
11301     if (IS_CODEPTR(type))
11302 #endif
11303       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11304
11305     /* if left is of type of pointer then it is simple */
11306     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11307       p_type = DCL_TYPE(type);
11308     else {
11309       /* we have to go by the storage class */
11310       p_type = PTR_TYPE(SPEC_OCLS(etype));
11311
11312       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11313
11314       if (SPEC_OCLS(etype)->codesp ) {
11315         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11316         //p_type = CPOINTER ;   
11317       } else
11318       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11319         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11320         /*p_type = FPOINTER ;*/ 
11321       } else
11322       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11323         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11324         /* p_type = PPOINTER; */
11325       } else
11326       if (SPEC_OCLS(etype) == idata ) {
11327         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11328         /* p_type = IPOINTER; */
11329       } else {
11330         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11331         /* p_type = POINTER ; */
11332       }
11333     }
11334
11335     /* now that we have the pointer type we assign
11336     the pointer values */
11337     switch (p_type) {
11338       case POINTER:     
11339       case IPOINTER:
11340         genNearPointerGet (left,result,ic);
11341         break;
11342
11343       case PPOINTER:
11344         genPagedPointerGet(left,result,ic);
11345         break;
11346
11347       case FPOINTER:
11348         genFarPointerGet (left,result,ic);
11349         break;
11350
11351       case CPOINTER:
11352         genConstPointerGet (left,result,ic);
11353         //pic16_emitcodePointerGet (left,result,ic);
11354         break;
11355
11356       case GPOINTER:
11357 #if 0
11358       if (IS_PTR_CONST(type))
11359         genConstPointerGet (left,result,ic);
11360       else
11361 #endif
11362         genGenPointerGet (left,result,ic);
11363       break;
11364
11365     default:
11366       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11367               "genPointerGet: illegal pointer type");
11368     
11369     }
11370 }
11371
11372 /*-----------------------------------------------------------------*/
11373 /* genPackBits - generates code for packed bit storage             */
11374 /*-----------------------------------------------------------------*/
11375 static void genPackBits (sym_link    *etype , operand *result,
11376                          operand *right ,
11377                          char *rname, int p_type)
11378 {
11379   int shCnt = 0 ;
11380   int offset = 0  ;
11381   int rLen = 0 ;
11382   int blen, bstr ;   
11383   sym_link *retype;
11384
11385         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11386         blen = SPEC_BLEN(etype);
11387         bstr = SPEC_BSTR(etype);
11388
11389         retype = getSpec(operandType(right));
11390
11391         if(AOP_TYPE(right) == AOP_LIT) {
11392                 if((blen == 1) && (bstr < 8)) {
11393                   unsigned long lit;
11394                         /* it is a single bit, so use the appropriate bit instructions */
11395
11396                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11397
11398                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11399 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11400                         if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11401                                 /* workaround to reduce the extra lfsr instruction */
11402                                 if(lit) {
11403                                         pic16_emitpcode(POC_BSF,
11404                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11405                                 } else {
11406                                         pic16_emitpcode(POC_BCF,
11407                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11408                                 }
11409                         } else {
11410                                 pic16_loadFSR0(result, 0);
11411                                 if(lit) {
11412                                         pic16_emitpcode(POC_BSF,
11413                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11414                                 } else {
11415                                         pic16_emitpcode(POC_BCF,
11416                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11417                                 }
11418                         }
11419         
11420                   return;
11421                 }
11422                 /* move literal to W */
11423                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11424                 offset++;
11425         } else
11426         if(IS_BITFIELD(retype) 
11427           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11428           && (blen == 1)) {
11429           int rblen, rbstr;
11430
11431             rblen = SPEC_BLEN( retype );
11432             rbstr = SPEC_BSTR( retype );
11433             
11434
11435             if(IS_BITFIELD(etype)) {
11436               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11437               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11438             } else {
11439               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11440             }
11441             
11442             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11443             
11444             if(IS_BITFIELD(etype)) {
11445               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11446             } else {
11447               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11448             }
11449
11450             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11451             
11452             return;
11453         } else {
11454           /* move right to W */
11455           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11456         }
11457
11458         /* if the bit length is less than or   */
11459         /* it exactly fits a byte then         */
11460         if((shCnt=SPEC_BSTR(etype))
11461                 || SPEC_BLEN(etype) <= 8 )  {
11462                 int fsr0_setup = 0;
11463
11464                 if (blen != 8 || bstr != 0) {
11465                   // we need to combine the value with the old value
11466                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11467
11468           DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11469                 SPEC_BSTR(etype), SPEC_BLEN(etype));
11470                 
11471                   /* shift left acc */
11472                   AccLsh(shCnt);
11473
11474                   /* using PRODH as a temporary register here */
11475                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11476
11477                  if (OP_SYMBOL(result)->remat) {
11478                    // access symbol directly
11479                    pic16_mov2w (AOP(result), 0);
11480                  } else {
11481                   /* get old value */
11482                   switch (p_type) {
11483                         case FPOINTER:
11484                         case POINTER:
11485                                 pic16_loadFSR0( result, 0 );
11486                                 fsr0_setup = 1;
11487                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11488 //                              pic16_emitcode ("mov","b,a");
11489 //                              pic16_emitcode("mov","a,@%s",rname);
11490                                 break;
11491
11492                         case GPOINTER:
11493                                 if (AOP(result)->aopu.aop_reg[2]) {
11494                                   // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
11495                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11496                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11497                                   pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11498
11499                                   pic16_callGenericPointerRW(0, 1);
11500                                 } else {
11501                                   // data pointer (just 2 byte given)
11502                                   pic16_loadFSR0( result, 0 );
11503                                   fsr0_setup = 1;
11504                                   pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11505                                 }
11506                                 
11507                                 // warnings will be emitted below
11508                                 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER...");
11509                                 //werror(W_POSSBUG2, __FILE__, __LINE__);
11510                                 break;
11511
11512                         default:
11513                                 assert (0 && "invalid pointer type specified");
11514                                 break;
11515                   }
11516                  }
11517 #if 1
11518                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11519                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11520                                         (unsigned char)(0xff >> (8-bstr))) ));
11521                   pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11522                 } // if (blen != 8 || bstr != 0)
11523
11524                 /* write new value back */
11525                if (OP_SYMBOL(result)->remat) {
11526                 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11527                } else {
11528                 switch (p_type) {
11529                         case FPOINTER:
11530                         case POINTER:
11531                                 if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11532                                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11533                                 break;
11534
11535                         case GPOINTER:
11536                                 if (AOP(result)->aopu.aop_reg[2]) {
11537                                   // prepare call to __gptrset1, this is actually genGenPointerSet(WREG, result, ?ic?)
11538                                   pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec/*pic16_pc_postdec1*/));
11539                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11540                                   pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11541                                   pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11542                                   
11543                                   pic16_callGenericPointerRW(1, 1);
11544                                 } else {
11545                                   // data pointer (just 2 byte given)
11546                                   if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11547                                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11548                                 }
11549                                 
11550                                 // this should work in all cases (as soon as gptrget/gptrput work on EEPROM and PROGRAM MEMORY)
11551                                 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER access");
11552                                 werror(W_POSSBUG2, __FILE__, __LINE__);
11553                                 break;
11554
11555                         default:
11556                                 assert (0 && "invalid pointer type specified");
11557                                 break;
11558                 }
11559                }
11560 #endif
11561
11562           return;
11563         }
11564
11565
11566 #if 0
11567         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11568         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11569         exit(-1);
11570 #endif
11571
11572
11573     pic16_loadFSR0(result, 0);                  // load FSR0 with address of result
11574     rLen = SPEC_BLEN(etype)-8;
11575     
11576     /* now generate for lengths greater than one byte */
11577     while (1) {
11578         rLen -= 8 ;
11579         if (rLen <= 0 ) {
11580           mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11581           break ;
11582         }
11583
11584         switch (p_type) {
11585             case POINTER:
11586                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11587                 break;
11588
11589 /*
11590             case FPOINTER:
11591                 MOVA(l);
11592                 pic16_emitcode("movx","@dptr,a");
11593                 break;
11594
11595             case GPOINTER:
11596                 MOVA(l);
11597                 DEBUGpic16_emitcode(";lcall","__gptrput");
11598                 break;  
11599 */
11600           default:
11601             assert(0);
11602         }   
11603
11604
11605         pic16_mov2w(AOP(right), offset++);
11606     }
11607
11608     /* last last was not complete */
11609     if (rLen)   {
11610         /* save the byte & read byte */
11611         switch (p_type) {
11612             case POINTER:
11613 //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11614                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11615                 break;
11616
11617 /*
11618             case FPOINTER:
11619                 pic16_emitcode ("mov","b,a");
11620                 pic16_emitcode("movx","a,@dptr");
11621                 break;
11622
11623             case GPOINTER:
11624                 pic16_emitcode ("push","b");
11625                 pic16_emitcode ("push","acc");
11626                 pic16_emitcode ("lcall","__gptrget");
11627                 pic16_emitcode ("pop","b");
11628                 break;
11629 */
11630             default:
11631               assert(0);
11632         }
11633         DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11634         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11635         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11636 //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11637 //        pic16_emitcode ("orl","a,b");
11638     }
11639
11640 //    if (p_type == GPOINTER)
11641 //        pic16_emitcode("pop","b");
11642
11643     switch (p_type) {
11644
11645       case POINTER:
11646         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11647 //      pic16_emitcode("mov","@%s,a",rname);
11648         break;
11649 /*
11650       case FPOINTER:
11651         pic16_emitcode("movx","@dptr,a");
11652         break;
11653         
11654       case GPOINTER:
11655         DEBUGpic16_emitcode(";lcall","__gptrput");
11656         break;                  
11657 */
11658       default:
11659         assert(0);
11660     }
11661     
11662 //    pic16_freeAsmop(right, NULL, ic, TRUE);
11663 }
11664 /*-----------------------------------------------------------------*/
11665 /* genDataPointerSet - remat pointer to data space                 */
11666 /*-----------------------------------------------------------------*/
11667 static void genDataPointerSet(operand *right,
11668                               operand *result,
11669                               iCode *ic)
11670 {
11671     int size, offset = 0, resoffset=0 ;
11672
11673     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11674     pic16_aopOp(right,ic,FALSE);
11675
11676     size = AOP_SIZE(right);
11677
11678 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11679
11680 #if 0
11681     if ( AOP_TYPE(result) == AOP_PCODE) {
11682       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11683               AOP(result)->aopu.pcop->name,
11684                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11685               PCOR(AOP(result)->aopu.pcop)->instance:
11686               PCOI(AOP(result)->aopu.pcop)->offset);
11687     }
11688 #endif
11689
11690         if(AOP(result)->aopu.pcop->type == PO_DIR)
11691                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11692
11693         while (size--) {
11694                 if (AOP_TYPE(right) == AOP_LIT) {
11695                   unsigned int lit;
11696
11697                     if(!IS_FLOAT(operandType( right )))
11698                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11699                     else {
11700                       union {
11701                         unsigned long lit_int;
11702                         float lit_float;
11703                       } info;
11704         
11705                         /* take care if literal is a float */
11706                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11707                         lit = info.lit_int;
11708                     }
11709
11710                     lit = lit >> (8*offset);
11711                     if(lit&0xff) {
11712                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11713                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11714                     } else {
11715                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11716                     }
11717                 } else {
11718                   pic16_mov2w(AOP(right), offset);
11719                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11720                 }
11721                 offset++;
11722                 resoffset++;
11723         }
11724
11725     pic16_freeAsmop(right,NULL,ic,TRUE);
11726 }
11727
11728
11729
11730 /*-----------------------------------------------------------------*/
11731 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11732 /*-----------------------------------------------------------------*/
11733 static void genNearPointerSet (operand *right,
11734                                operand *result, 
11735                                iCode *ic)
11736 {
11737   asmop *aop = NULL;
11738   sym_link *retype;
11739   sym_link *ptype = operandType(result);
11740   sym_link *resetype;
11741     
11742         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11743         retype= getSpec(operandType(right));
11744         resetype = getSpec(operandType(result));
11745   
11746         pic16_aopOp(result,ic,FALSE);
11747     
11748         /* if the result is rematerializable &
11749          * in data space & not a bit variable */
11750         
11751         /* and result is not a bit variable */
11752         if (AOP_TYPE(result) == AOP_PCODE
11753 //              && AOP_TYPE(result) == AOP_IMMD
11754                 && DCL_TYPE(ptype) == POINTER
11755                 && !IS_BITFIELD(retype)
11756                 && !IS_BITFIELD(resetype)) {
11757
11758                 genDataPointerSet (right,result,ic);
11759                 pic16_freeAsmop(result,NULL,ic,TRUE);
11760           return;
11761         }
11762
11763         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11764         pic16_aopOp(right,ic,FALSE);
11765         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11766
11767         /* if the value is already in a pointer register
11768          * then don't need anything more */
11769         if (1 || !AOP_INPREG(AOP(result))) {  // AOP_INPREG(AOP(result)) is not always correct...
11770           /* otherwise get a free pointer register */
11771           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11772
11773           ;
11774         }
11775
11776         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11777
11778         /* if bitfield then unpack the bits */
11779         if (IS_BITFIELD(resetype)) {
11780                 genPackBits (resetype, result, right, NULL, POINTER);
11781         } else {
11782                 /* we have can just get the values */
11783           int size = AOP_SIZE(right);
11784           int offset = 0 ;    
11785
11786             pic16_loadFSR0(result, 0);
11787             
11788                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11789                 while (size--) {
11790                                 if (AOP_TYPE(right) == AOP_LIT) {
11791                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11792                                         if (size) {
11793                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11794                                         } else {
11795                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11796                                         }
11797                                 } else { // no literal
11798                                         if(size) {
11799                                                 pic16_emitpcode(POC_MOVFF,
11800                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11801                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11802                                         } else {
11803                                                 pic16_emitpcode(POC_MOVFF,
11804                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11805                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11806                                         }
11807                                 }
11808                         offset++;
11809                 }
11810         }
11811
11812         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11813         /* now some housekeeping stuff */
11814         if (aop) {
11815           /* we had to allocate for this iCode */
11816           pic16_freeAsmop(NULL,aop,ic,TRUE);
11817         } else { 
11818           /* we did not allocate which means left
11819            * already in a pointer register, then
11820            * if size > 0 && this could be used again
11821            * we have to point it back to where it 
11822            * belongs */
11823           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11824           if (AOP_SIZE(right) > 1
11825             && !OP_SYMBOL(result)->remat
11826             && ( OP_SYMBOL(result)->liveTo > ic->seq
11827             || ic->depth )) {
11828
11829               int size = AOP_SIZE(right) - 1;
11830
11831                 while (size--)
11832                   pic16_emitcode("decf","fsr0,f");
11833                   //pic16_emitcode("dec","%s",rname);
11834             }
11835         }
11836
11837     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11838     /* done */
11839 //release:
11840     pic16_freeAsmop(right,NULL,ic,TRUE);
11841     pic16_freeAsmop(result,NULL,ic,TRUE);
11842 }
11843
11844 /*-----------------------------------------------------------------*/
11845 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11846 /*-----------------------------------------------------------------*/
11847 static void genPagedPointerSet (operand *right,
11848                                operand *result, 
11849                                iCode *ic)
11850 {
11851     asmop *aop = NULL;
11852     regs *preg = NULL ;
11853     char *rname , *l;
11854     sym_link *retype;
11855        
11856     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11857
11858     retype= getSpec(operandType(right));
11859     
11860     pic16_aopOp(result,ic,FALSE);
11861     
11862     /* if the value is already in a pointer register
11863        then don't need anything more */
11864     if (!AOP_INPREG(AOP(result))) {
11865         /* otherwise get a free pointer register */
11866         aop = newAsmop(0);
11867         preg = getFreePtr(ic,&aop,FALSE);
11868         pic16_emitcode("mov","%s,%s",
11869                 preg->name,
11870                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11871         rname = preg->name ;
11872     } else
11873         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11874     
11875     pic16_freeAsmop(result,NULL,ic,TRUE);
11876     pic16_aopOp (right,ic,FALSE);
11877
11878     /* if bitfield then unpack the bits */
11879     if (IS_BITFIELD(retype)) 
11880         genPackBits (retype,result,right,rname,PPOINTER);
11881     else {
11882         /* we have can just get the values */
11883         int size = AOP_SIZE(right);
11884         int offset = 0 ;        
11885         
11886         while (size--) {
11887             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11888             
11889             MOVA(l);
11890             pic16_emitcode("movx","@%s,a",rname);
11891
11892             if (size)
11893                 pic16_emitcode("inc","%s",rname);
11894
11895             offset++;
11896         }
11897     }
11898     
11899     /* now some housekeeping stuff */
11900     if (aop) {
11901         /* we had to allocate for this iCode */
11902         pic16_freeAsmop(NULL,aop,ic,TRUE);
11903     } else { 
11904         /* we did not allocate which means left
11905            already in a pointer register, then
11906            if size > 0 && this could be used again
11907            we have to point it back to where it 
11908            belongs */
11909         if (AOP_SIZE(right) > 1 &&
11910             !OP_SYMBOL(result)->remat &&
11911             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11912               ic->depth )) {
11913             int size = AOP_SIZE(right) - 1;
11914             while (size--)
11915                 pic16_emitcode("dec","%s",rname);
11916         }
11917     }
11918
11919     /* done */
11920     pic16_freeAsmop(right,NULL,ic,TRUE);
11921     
11922         
11923 }
11924
11925 /*-----------------------------------------------------------------*/
11926 /* genFarPointerSet - set value from far space                     */
11927 /*-----------------------------------------------------------------*/
11928 static void genFarPointerSet (operand *right,
11929                               operand *result, iCode *ic)
11930 {
11931     int size, offset ;
11932     sym_link *retype = getSpec(operandType(right));
11933
11934     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11935     pic16_aopOp(result,ic,FALSE);
11936
11937     /* if the operand is already in dptr 
11938     then we do nothing else we move the value to dptr */
11939     if (AOP_TYPE(result) != AOP_STR) {
11940         /* if this is remateriazable */
11941         if (AOP_TYPE(result) == AOP_IMMD)
11942             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11943         else { /* we need to get it byte by byte */
11944             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11945             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11946             if (options.model == MODEL_FLAT24)
11947             {
11948                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11949             }
11950         }
11951     }
11952     /* so dptr know contains the address */
11953     pic16_freeAsmop(result,NULL,ic,TRUE);
11954     pic16_aopOp(right,ic,FALSE);
11955
11956     /* if bit then unpack */
11957     if (IS_BITFIELD(retype)) 
11958         genPackBits(retype,result,right,"dptr",FPOINTER);
11959     else {
11960         size = AOP_SIZE(right);
11961         offset = 0 ;
11962
11963         while (size--) {
11964             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11965             MOVA(l);
11966             pic16_emitcode("movx","@dptr,a");
11967             if (size)
11968                 pic16_emitcode("inc","dptr");
11969         }
11970     }
11971
11972     pic16_freeAsmop(right,NULL,ic,TRUE);
11973 }
11974
11975 /*-----------------------------------------------------------------*/
11976 /* genGenPointerSet - set value from generic pointer space         */
11977 /*-----------------------------------------------------------------*/
11978 #if 0
11979 static void genGenPointerSet (operand *right,
11980                               operand *result, iCode *ic)
11981 {
11982         int i, size, offset, lit;
11983         sym_link *retype = getSpec(operandType(right));
11984
11985         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11986
11987         pic16_aopOp(result,ic,FALSE);
11988         pic16_aopOp(right,ic,FALSE);
11989         size = AOP_SIZE(right);
11990         offset = 0;
11991
11992         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11993
11994         /* if the operand is already in dptr 
11995                 then we do nothing else we move the value to dptr */
11996         if (AOP_TYPE(result) != AOP_STR) {
11997                 /* if this is remateriazable */
11998                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11999                 // WARNING: anythig until "else" is untested!
12000                 if (AOP_TYPE(result) == AOP_IMMD) {
12001                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12002                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12003                         // load FSR0 from immediate
12004                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12005                         offset = 0;
12006                         while(size--) {
12007                                 if(size) {
12008                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12009                                 } else {
12010                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12011                                 }
12012                                 offset++;
12013                         }
12014                         goto release;
12015                 }
12016                 else { /* we need to get it byte by byte */
12017                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12018                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12019
12020                         // set up FSR0 with address of result
12021                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12022                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12023
12024                         /* hack hack! see if this the FSR. If so don't load W */
12025                         if(AOP_TYPE(right) != AOP_ACC) {
12026
12027                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12028
12029                                 if(AOP_TYPE(right) == AOP_LIT)
12030                                 {
12031                                         // copy literal
12032                                         // note: pic16_popGet handles sign extension
12033                                         for(i=0;i<size;i++) {
12034                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12035                                                 if(i < size-1)
12036                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12037                                                 else
12038                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12039                                         }
12040                                 } else {
12041                                         // copy regs
12042
12043                                         for(i=0;i<size;i++) {
12044                                                 if(i < size-1)
12045                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12046                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12047                                                 else
12048                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12049                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12050                                         }
12051                                 }
12052                                 goto release;
12053                         } 
12054                         // right = ACC
12055                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12056                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12057                         goto release;
12058         } // if (AOP_TYPE(result) != AOP_IMMD)
12059
12060         } // if (AOP_TYPE(result) != AOP_STR)
12061         /* so dptr know contains the address */
12062
12063
12064         /* if bit then unpack */
12065         if (IS_BITFIELD(retype)) 
12066                 genPackBits(retype,result,right,"dptr",GPOINTER);
12067         else {
12068                 size = AOP_SIZE(right);
12069                 offset = 0 ;
12070
12071                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12072
12073                 // set up FSR0 with address of result
12074                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12075                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12076         
12077                 while (size--) {
12078                         if (AOP_TYPE(right) == AOP_LIT) {
12079                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12080                                 if (size) {
12081                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12082                                 } else {
12083                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12084                                 }
12085                         } else { // no literal
12086                                 if(size) {
12087                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12088                                 } else {
12089                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12090                                 }
12091                         }
12092                         offset++;
12093                 }
12094         }
12095
12096         release:
12097         pic16_freeAsmop(right,NULL,ic,TRUE);
12098         pic16_freeAsmop(result,NULL,ic,TRUE);
12099 }
12100 #endif
12101
12102 static void genGenPointerSet (operand *right,
12103                               operand *result, iCode *ic)
12104 {
12105   int size;
12106   sym_link *retype = getSpec(operandType(right));
12107
12108     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12109
12110     pic16_aopOp(result,ic,FALSE);
12111     pic16_aopOp(right,ic,FALSE);
12112     size = AOP_SIZE(right);
12113
12114     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12115
12116
12117     /* if bit then unpack */
12118     if (IS_BITFIELD(retype)) {
12119 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12120       genPackBits(retype,result,right,"dptr",GPOINTER);
12121       goto release;
12122     }
12123
12124     size = AOP_SIZE(right);
12125
12126     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12127
12128
12129
12130     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12131
12132     /* value of right+0 is placed on stack, which will be retrieved
12133      * by the support function this restoring the stack. The important
12134      * thing is that there is no need to manually restore stack pointer
12135      * here */
12136     pushaop(AOP(right), 0);
12137 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12138     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12139     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12140     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12141     
12142     /* load address to write to in WREG:FSR0H:FSR0L */
12143     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12144                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12145     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12146                                 pic16_popCopyReg(&pic16_pc_prodl)));
12147     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12148     
12149     pic16_callGenericPointerRW(1, size);
12150
12151 release:
12152     pic16_freeAsmop(right,NULL,ic,TRUE);
12153     pic16_freeAsmop(result,NULL,ic,TRUE);
12154 }
12155
12156 /*-----------------------------------------------------------------*/
12157 /* genPointerSet - stores the value into a pointer location        */
12158 /*-----------------------------------------------------------------*/
12159 static void genPointerSet (iCode *ic)
12160 {    
12161   operand *right, *result ;
12162   sym_link *type, *etype;
12163   int p_type;
12164
12165     FENTRY;
12166
12167     right = IC_RIGHT(ic);
12168     result = IC_RESULT(ic) ;
12169
12170     /* depending on the type of pointer we need to
12171     move it to the correct pointer register */
12172     type = operandType(result);
12173     etype = getSpec(type);
12174     /* if left is of type of pointer then it is simple */
12175     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12176         p_type = DCL_TYPE(type);
12177     }
12178     else {
12179         /* we have to go by the storage class */
12180         p_type = PTR_TYPE(SPEC_OCLS(etype));
12181
12182 /*      if (SPEC_OCLS(etype)->codesp ) { */
12183 /*          p_type = CPOINTER ;  */
12184 /*      } */
12185 /*      else */
12186 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12187 /*              p_type = FPOINTER ; */
12188 /*          else */
12189 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12190 /*                  p_type = PPOINTER ; */
12191 /*              else */
12192 /*                  if (SPEC_OCLS(etype) == idata ) */
12193 /*                      p_type = IPOINTER ; */
12194 /*                  else */
12195 /*                      p_type = POINTER ; */
12196     }
12197
12198     /* now that we have the pointer type we assign
12199     the pointer values */
12200     switch (p_type) {
12201       case POINTER:
12202       case IPOINTER:
12203         genNearPointerSet (right,result,ic);
12204         break;
12205
12206       case PPOINTER:
12207         genPagedPointerSet (right,result,ic);
12208         break;
12209
12210       case FPOINTER:
12211         genFarPointerSet (right,result,ic);
12212         break;
12213         
12214       case GPOINTER:
12215         genGenPointerSet (right,result,ic);
12216         break;
12217
12218       default:
12219         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12220           "genPointerSet: illegal pointer type");
12221     }
12222 }
12223
12224 /*-----------------------------------------------------------------*/
12225 /* genIfx - generate code for Ifx statement                        */
12226 /*-----------------------------------------------------------------*/
12227 static void genIfx (iCode *ic, iCode *popIc)
12228 {
12229   operand *cond = IC_COND(ic);
12230   int isbit =0;
12231
12232     FENTRY;
12233
12234     pic16_aopOp(cond,ic,FALSE);
12235
12236     /* get the value into acc */
12237     if (AOP_TYPE(cond) != AOP_CRY)
12238       pic16_toBoolean(cond);
12239     else
12240       isbit = 1;
12241     /* the result is now in the accumulator */
12242     pic16_freeAsmop(cond,NULL,ic,TRUE);
12243
12244     /* if there was something to be popped then do it */
12245     if (popIc)
12246       genIpop(popIc);
12247
12248     /* if the condition is  a bit variable */
12249     if (isbit && IS_ITEMP(cond) && 
12250         SPIL_LOC(cond)) {
12251       genIfxJump(ic,"c");
12252       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12253     } else {
12254       if (isbit && !IS_ITEMP(cond))
12255         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12256         else
12257         genIfxJump(ic,"a");
12258     }
12259     ic->generated = 1;
12260 }
12261
12262 /*-----------------------------------------------------------------*/
12263 /* genAddrOf - generates code for address of                       */
12264 /*-----------------------------------------------------------------*/
12265 static void genAddrOf (iCode *ic)
12266 {
12267   operand *result, *left;
12268   int size;
12269   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12270   pCodeOp *pcop0, *pcop1, *pcop2;
12271
12272     FENTRY;
12273
12274     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12275
12276     sym = OP_SYMBOL( IC_LEFT(ic) );
12277     
12278     if(sym->onStack) {
12279       /* get address of symbol on stack */
12280       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12281 #if 0
12282       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12283                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12284 #endif
12285
12286       // operands on stack are accessible via "FSR2 + index" with index
12287       // starting at 2 for arguments and growing from 0 downwards for
12288       // local variables (index == 0 is not assigned so we add one here)
12289       {
12290         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12291         if (soffs <= 0) {
12292           assert (soffs < 0);
12293           soffs++;
12294         } // if
12295         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12296         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12297         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12298         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12299         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12300         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12301         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12302       }
12303
12304       goto release;
12305     }
12306         
12307 //      if(pic16_debug_verbose) {
12308 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12309 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12310 //      }
12311         
12312     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12313     size = AOP_SIZE(IC_RESULT(ic));
12314
12315     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12316     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12317     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12318         
12319     if (size == 3) {
12320       pic16_emitpcode(POC_MOVLW, pcop0);
12321       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12322       pic16_emitpcode(POC_MOVLW, pcop1);
12323       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12324       pic16_emitpcode(POC_MOVLW, pcop2);
12325       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12326     } else
12327     if (size == 2) {
12328       pic16_emitpcode(POC_MOVLW, pcop0);
12329       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12330       pic16_emitpcode(POC_MOVLW, pcop1);
12331     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12332     } else {
12333       pic16_emitpcode(POC_MOVLW, pcop0);
12334       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12335     }
12336
12337     pic16_freeAsmop(left, NULL, ic, FALSE);
12338 release:
12339     pic16_freeAsmop(result,NULL,ic,TRUE);
12340 }
12341
12342
12343 #if 0
12344 /*-----------------------------------------------------------------*/
12345 /* genFarFarAssign - assignment when both are in far space         */
12346 /*-----------------------------------------------------------------*/
12347 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12348 {
12349     int size = AOP_SIZE(right);
12350     int offset = 0;
12351     char *l ;
12352     /* first push the right side on to the stack */
12353     while (size--) {
12354         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12355         MOVA(l);
12356         pic16_emitcode ("push","acc");
12357     }
12358     
12359     pic16_freeAsmop(right,NULL,ic,FALSE);
12360     /* now assign DPTR to result */
12361     pic16_aopOp(result,ic,FALSE);
12362     size = AOP_SIZE(result);
12363     while (size--) {
12364         pic16_emitcode ("pop","acc");
12365         pic16_aopPut(AOP(result),"a",--offset);
12366     }
12367     pic16_freeAsmop(result,NULL,ic,FALSE);
12368         
12369 }
12370 #endif
12371
12372 /*-----------------------------------------------------------------*/
12373 /* genAssign - generate code for assignment                        */
12374 /*-----------------------------------------------------------------*/
12375 static void genAssign (iCode *ic)
12376 {
12377   operand *result, *right;
12378   int size, offset,know_W;
12379   unsigned long lit = 0L;
12380
12381   result = IC_RESULT(ic);
12382   right  = IC_RIGHT(ic) ;
12383
12384   FENTRY;
12385   
12386   /* if they are the same */
12387   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12388     return ;
12389
12390   /* reversed order operands are aopOp'ed so that result operand
12391    * is effective in case right is a stack symbol. This maneauver
12392    * allows to use the _G.resDirect flag later */
12393   pic16_aopOp(result,ic,TRUE);
12394   pic16_aopOp(right,ic,FALSE);
12395
12396   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12397
12398   /* if they are the same registers */
12399   if (pic16_sameRegs(AOP(right),AOP(result)))
12400     goto release;
12401
12402   /* if the result is a bit */
12403   if (AOP_TYPE(result) == AOP_CRY) {
12404     /* if the right size is a literal then
12405        we know what the value is */
12406     if (AOP_TYPE(right) == AOP_LIT) {
12407           
12408       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12409                   pic16_popGet(AOP(result),0));
12410
12411       if (((int) operandLitValue(right))) 
12412         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12413                        AOP(result)->aopu.aop_dir,
12414                        AOP(result)->aopu.aop_dir);
12415       else
12416         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12417                        AOP(result)->aopu.aop_dir,
12418                        AOP(result)->aopu.aop_dir);
12419       goto release;
12420     }
12421
12422     /* the right is also a bit variable */
12423     if (AOP_TYPE(right) == AOP_CRY) {
12424       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12425       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12426       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12427
12428       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12429                      AOP(result)->aopu.aop_dir,
12430                      AOP(result)->aopu.aop_dir);
12431       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12432                      AOP(right)->aopu.aop_dir,
12433                      AOP(right)->aopu.aop_dir);
12434       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12435                      AOP(result)->aopu.aop_dir,
12436                      AOP(result)->aopu.aop_dir);
12437       goto release ;
12438     }
12439
12440     /* we need to or */
12441     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12442     pic16_toBoolean(right);
12443     emitSKPZ;
12444     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12445     //pic16_aopPut(AOP(result),"a",0);
12446     goto release ;
12447   }
12448
12449   /* bit variables done */
12450   /* general case */
12451   size = AOP_SIZE(result);
12452   offset = 0 ;
12453
12454   if(AOP_TYPE(right) == AOP_LIT) {
12455         if(!IS_FLOAT(operandType( right )))
12456                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12457         else {
12458            union {
12459               unsigned long lit_int;
12460               float lit_float;
12461             } info;
12462         
12463                 /* take care if literal is a float */
12464                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12465                 lit = info.lit_int;
12466         }
12467   }
12468
12469 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12470 //                      sizeof(unsigned long int), sizeof(float));
12471
12472
12473   if (AOP_TYPE(right) == AOP_REG) {
12474     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12475     while (size--) {
12476       
12477       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12478     } // while
12479     goto release;
12480   }
12481
12482   if(AOP_TYPE(right) != AOP_LIT
12483         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12484         && !IS_FUNC(OP_SYM_TYPE(right))
12485         ) {
12486         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12487         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12488
12489         // set up table pointer
12490         if(is_LitOp(right)) {
12491 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12492                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12493                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12494                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12495                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12496                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12497                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12498         } else {
12499 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12500                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12501                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12502                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12503                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12504                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12505                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12506         }
12507
12508         size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
12509         while(size--) {
12510                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12511                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12512                         pic16_popGet(AOP(result),offset)));
12513                 offset++;
12514         }
12515
12516         size = getSize(OP_SYM_ETYPE(right));
12517         if(AOP_SIZE(result) > size) {
12518                 size = AOP_SIZE(result) - size;
12519                 while(size--) {
12520                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12521                         offset++;
12522                 }
12523         }
12524         goto release;
12525   }
12526
12527
12528
12529 #if 0
12530 /* VR - What is this?! */
12531   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12532     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12533     if(aopIdx(AOP(result),0) == 4) {
12534
12535       /* this is a workaround to save value of right into wreg too,
12536        * value of wreg is going to be used later */
12537       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12538       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12539       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12540       goto release;
12541     } else
12542 //      assert(0);
12543       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12544   }
12545 #endif
12546
12547   know_W=-1;
12548   while (size--) {
12549   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12550     if(AOP_TYPE(right) == AOP_LIT) {
12551       if(lit&0xff) {
12552         if(know_W != (lit&0xff))
12553           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12554         know_W = lit&0xff;
12555         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12556       } else
12557         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12558
12559       lit >>= 8;
12560
12561     } else if (AOP_TYPE(right) == AOP_CRY) {
12562       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12563       if(offset == 0) {
12564         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12565         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12566         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12567       }
12568     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12569         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12570         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12571     } else {
12572       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12573
12574       if(!_G.resDirect)         /* use this aopForSym feature */
12575         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12576     }
12577             
12578     offset++;
12579   }
12580   
12581  release:
12582   pic16_freeAsmop (right,NULL,ic,FALSE);
12583   pic16_freeAsmop (result,NULL,ic,TRUE);
12584 }   
12585
12586 /*-----------------------------------------------------------------*/
12587 /* genJumpTab - generates code for jump table                       */
12588 /*-----------------------------------------------------------------*/
12589 static void genJumpTab (iCode *ic)
12590 {
12591   symbol *jtab;
12592   char *l;
12593   pCodeOp *jt_offs;
12594   pCodeOp *jt_offs_hi;
12595   pCodeOp *jt_label;
12596
12597     FENTRY;
12598
12599     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12600     /* get the condition into accumulator */
12601     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12602     MOVA(l);
12603     /* multiply by three */
12604     pic16_emitcode("add","a,acc");
12605     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12606
12607     jtab = newiTempLabel(NULL);
12608     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12609     pic16_emitcode("jmp","@a+dptr");
12610     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12611
12612 #if 0
12613     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12614     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12615     emitSKPNC;
12616     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12617     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12618     pic16_emitpLabel(jtab->key);
12619
12620 #else
12621
12622     jt_offs = pic16_popGetTempReg(0);
12623     jt_offs_hi = pic16_popGetTempReg(1);
12624     jt_label = pic16_popGetLabel (jtab->key);
12625     //fprintf (stderr, "Creating jump table...\n");
12626
12627     // calculate offset into jump table (idx * sizeof (GOTO))
12628     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12629     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12630     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12631     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12632     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12633     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12634     pic16_emitpcode(POC_MOVWF , jt_offs);
12635
12636     // prepare PCLATx (set to first entry in jump table)
12637     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12638     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12639     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12640     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12641     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12642
12643     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12644     pic16_emitpcode(POC_ADDWF , jt_offs);
12645     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12646     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12647     emitSKPNC;
12648     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12649
12650     // release temporaries and prepare jump into table (new PCL --> WREG)
12651     pic16_emitpcode(POC_MOVFW , jt_offs);
12652     pic16_popReleaseTempReg (jt_offs_hi, 1);
12653     pic16_popReleaseTempReg (jt_offs, 0);
12654
12655     // jump into the table
12656     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12657
12658     pic16_emitpLabelFORCE(jtab->key);
12659 #endif
12660
12661     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12662 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12663
12664     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12665     /* now generate the jump labels */
12666     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12667          jtab = setNextItem(IC_JTLABELS(ic))) {
12668 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12669         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12670         
12671     }
12672     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12673
12674 }
12675
12676 /*-----------------------------------------------------------------*/
12677 /* genMixedOperation - gen code for operators between mixed types  */
12678 /*-----------------------------------------------------------------*/
12679 /*
12680   TSD - Written for the PIC port - but this unfortunately is buggy.
12681   This routine is good in that it is able to efficiently promote 
12682   types to different (larger) sizes. Unfortunately, the temporary
12683   variables that are optimized out by this routine are sometimes
12684   used in other places. So until I know how to really parse the 
12685   iCode tree, I'm going to not be using this routine :(.
12686 */
12687 static int genMixedOperation (iCode *ic)
12688 {
12689 #if 0
12690   operand *result = IC_RESULT(ic);
12691   sym_link *ctype = operandType(IC_LEFT(ic));
12692   operand *right = IC_RIGHT(ic);
12693   int ret = 0;
12694   int big,small;
12695   int offset;
12696
12697   iCode *nextic;
12698   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12699
12700   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12701
12702   nextic = ic->next;
12703   if(!nextic)
12704     return 0;
12705
12706   nextright = IC_RIGHT(nextic);
12707   nextleft  = IC_LEFT(nextic);
12708   nextresult = IC_RESULT(nextic);
12709
12710   pic16_aopOp(right,ic,FALSE);
12711   pic16_aopOp(result,ic,FALSE);
12712   pic16_aopOp(nextright,  nextic, FALSE);
12713   pic16_aopOp(nextleft,   nextic, FALSE);
12714   pic16_aopOp(nextresult, nextic, FALSE);
12715
12716   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12717
12718     operand *t = right;
12719     right = nextright;
12720     nextright = t; 
12721
12722     pic16_emitcode(";remove right +","");
12723
12724   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12725 /*
12726     operand *t = right;
12727     right = nextleft;
12728     nextleft = t; 
12729 */
12730     pic16_emitcode(";remove left +","");
12731   } else
12732     return 0;
12733
12734   big = AOP_SIZE(nextleft);
12735   small = AOP_SIZE(nextright);
12736
12737   switch(nextic->op) {
12738
12739   case '+':
12740     pic16_emitcode(";optimize a +","");
12741     /* if unsigned or not an integral type */
12742     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12743       pic16_emitcode(";add a bit to something","");
12744     } else {
12745
12746       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12747
12748       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12749         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12750         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12751       } else
12752         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12753
12754       offset = 0;
12755       while(--big) {
12756
12757         offset++;
12758
12759         if(--small) {
12760           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12761             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12762             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12763           }
12764
12765           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12766           emitSKPNC;
12767           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12768                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12769                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12770           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12771           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12772
12773         } else {
12774           pic16_emitcode("rlf","known_zero,w");
12775
12776           /*
12777             if right is signed
12778               btfsc  right,7
12779                addlw ff
12780           */
12781           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12782             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12783             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12784           } else {
12785             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12786           }
12787         }
12788       }
12789       ret = 1;
12790     }
12791   }
12792   ret = 1;
12793
12794 release:
12795   pic16_freeAsmop(right,NULL,ic,TRUE);
12796   pic16_freeAsmop(result,NULL,ic,TRUE);
12797   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12798   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12799   if(ret)
12800     nextic->generated = 1;
12801
12802   return ret;
12803 #else
12804   return 0;
12805 #endif
12806 }
12807 /*-----------------------------------------------------------------*/
12808 /* genCast - gen code for casting                                  */
12809 /*-----------------------------------------------------------------*/
12810 static void genCast (iCode *ic)
12811 {
12812   operand *result = IC_RESULT(ic);
12813   sym_link *ctype = operandType(IC_LEFT(ic));
12814   sym_link *rtype = operandType(IC_RIGHT(ic));
12815   sym_link *restype = operandType(IC_RESULT(ic));
12816   operand *right = IC_RIGHT(ic);
12817   int size, offset ;
12818
12819
12820     FENTRY;
12821
12822         /* if they are equivalent then do nothing */
12823 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12824 //              return ;
12825
12826         pic16_aopOp(result,ic,FALSE);
12827         pic16_aopOp(right,ic,FALSE) ;
12828
12829         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12830
12831
12832         /* if the result is a bit */
12833         if (AOP_TYPE(result) == AOP_CRY) {
12834         
12835                 /* if the right size is a literal then
12836                  * we know what the value is */
12837                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12838
12839                 if (AOP_TYPE(right) == AOP_LIT) {
12840                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12841                                 pic16_popGet(AOP(result),0));
12842
12843                         if (((int) operandLitValue(right))) 
12844                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12845                                         AOP(result)->aopu.aop_dir,
12846                                         AOP(result)->aopu.aop_dir);
12847                         else
12848                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12849                                         AOP(result)->aopu.aop_dir,
12850                                         AOP(result)->aopu.aop_dir);
12851                         goto release;
12852                 }
12853
12854                 /* the right is also a bit variable */
12855                 if (AOP_TYPE(right) == AOP_CRY) {
12856                         emitCLRC;
12857                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12858
12859                         pic16_emitcode("clrc","");
12860                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12861                                 AOP(right)->aopu.aop_dir,
12862                                 AOP(right)->aopu.aop_dir);
12863                         pic16_aopPut(AOP(result),"c",0);
12864                         goto release ;
12865                 }
12866
12867                 /* we need to or */
12868                 if (AOP_TYPE(right) == AOP_REG) {
12869                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12870                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12871                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12872                 }
12873                 pic16_toBoolean(right);
12874                 pic16_aopPut(AOP(result),"a",0);
12875                 goto release ;
12876         }
12877
12878         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12879           int offset = 1;
12880
12881                 size = AOP_SIZE(result);
12882
12883                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12884
12885                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12886                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12887                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12888
12889                 while (size--)
12890                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12891
12892                 goto release;
12893         }
12894
12895         if(IS_BITFIELD(getSpec(restype))
12896           && IS_BITFIELD(getSpec(rtype))) {
12897           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12898         }
12899
12900         /* if they are the same size : or less */
12901         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12902
12903                 /* if they are in the same place */
12904                 if (pic16_sameRegs(AOP(right),AOP(result)))
12905                         goto release;
12906
12907                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12908 #if 0
12909                 if (IS_PTR_CONST(rtype))
12910 #else
12911                 if (IS_CODEPTR(rtype))
12912 #endif
12913                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12914
12915 #if 0
12916                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12917 #else
12918                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12919 #endif
12920                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12921
12922 #if 0
12923                 if(AOP_TYPE(right) == AOP_IMMD) {
12924                   pCodeOp *pcop0, *pcop1, *pcop2;
12925                   symbol *sym = OP_SYMBOL( right );
12926
12927                         size = AOP_SIZE(result);
12928                         /* low */
12929                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12930                         /* high */
12931                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12932                         /* upper */
12933                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12934         
12935                         if (size == 3) {
12936                                 pic16_emitpcode(POC_MOVLW, pcop0);
12937                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12938                                 pic16_emitpcode(POC_MOVLW, pcop1);
12939                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12940                                 pic16_emitpcode(POC_MOVLW, pcop2);
12941                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12942                         } else
12943                         if (size == 2) {
12944                                 pic16_emitpcode(POC_MOVLW, pcop0);
12945                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12946                                 pic16_emitpcode(POC_MOVLW, pcop1);
12947                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12948                         } else {
12949                                 pic16_emitpcode(POC_MOVLW, pcop0);
12950                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12951                         }
12952                 } else
12953 #endif
12954                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12955                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12956                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12957                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12958                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12959                         if(AOP_SIZE(result) <2)
12960                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12961                 } else {
12962                         /* if they in different places then copy */
12963                         size = AOP_SIZE(result);
12964                         offset = 0 ;
12965                         while (size--) {
12966                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12967                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12968                                 offset++;
12969                         }
12970                 }
12971                 goto release;
12972         }
12973
12974         /* if the result is of type pointer */
12975         if (IS_PTR(ctype)) {
12976           int p_type;
12977           sym_link *type = operandType(right);
12978           sym_link *etype = getSpec(type);
12979
12980                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
12981
12982                 /* pointer to generic pointer */
12983                 if (IS_GENPTR(ctype)) {
12984                   char *l = zero;
12985             
12986                         if (IS_PTR(type)) 
12987                                 p_type = DCL_TYPE(type);
12988                         else {
12989                 /* we have to go by the storage class */
12990                 p_type = PTR_TYPE(SPEC_OCLS(etype));
12991
12992 /*              if (SPEC_OCLS(etype)->codesp )  */
12993 /*                  p_type = CPOINTER ;  */
12994 /*              else */
12995 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12996 /*                      p_type = FPOINTER ; */
12997 /*                  else */
12998 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12999 /*                          p_type = PPOINTER; */
13000 /*                      else */
13001 /*                          if (SPEC_OCLS(etype) == idata ) */
13002 /*                              p_type = IPOINTER ; */
13003 /*                          else */
13004 /*                              p_type = POINTER ; */
13005             }
13006                 
13007             /* the first two bytes are known */
13008       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13009             size = GPTRSIZE - 1; 
13010             offset = 0 ;
13011             while (size--) {
13012               if(offset < AOP_SIZE(right)) {
13013                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13014                 mov2f(AOP(result), AOP(right), offset);
13015 /*
13016                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13017                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13018                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13019                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13020                 } else { 
13021                   
13022                   pic16_aopPut(AOP(result),
13023                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13024                          offset);
13025                 }
13026 */
13027               } else 
13028                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13029               offset++;
13030             }
13031             /* the last byte depending on type */
13032             switch (p_type) {
13033             case IPOINTER:
13034             case POINTER:
13035                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13036                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13037 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13038                 break;
13039
13040             case CPOINTER:
13041                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13042                 break;
13043
13044             case FPOINTER:
13045               pic16_emitcode(";BUG!? ","%d",__LINE__);
13046                 l = one;
13047                 break;
13048             case PPOINTER:
13049               pic16_emitcode(";BUG!? ","%d",__LINE__);
13050                 l = "#0x03";
13051                 break;
13052
13053             case GPOINTER:
13054                 if (GPTRSIZE > AOP_SIZE(right)) {
13055                   // assume data pointer... THIS MIGHT BE WRONG!
13056                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13057                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13058                 } else {
13059                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13060                 }
13061               break;
13062               
13063             default:
13064                 /* this should never happen */
13065                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13066                        "got unknown pointer type");
13067                 exit(1);
13068             }
13069             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13070             goto release ;
13071         }
13072         
13073         
13074         assert( 0 );
13075         /* just copy the pointers */
13076         size = AOP_SIZE(result);
13077         offset = 0 ;
13078         while (size--) {
13079             pic16_aopPut(AOP(result),
13080                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13081                    offset);
13082             offset++;
13083         }
13084         goto release ;
13085     }
13086     
13087
13088
13089     /* so we now know that the size of destination is greater
13090     than the size of the source.
13091     Now, if the next iCode is an operator then we might be
13092     able to optimize the operation without performing a cast.
13093     */
13094     if(genMixedOperation(ic))
13095       goto release;
13096
13097     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13098     
13099     /* we move to result for the size of source */
13100     size = AOP_SIZE(right);
13101     offset = 0 ;
13102
13103     while (size--) {
13104       if(!_G.resDirect)
13105         mov2f(AOP(result), AOP(right), offset);
13106       offset++;
13107     }
13108
13109     /* now depending on the sign of the destination */
13110     size = AOP_SIZE(result) - AOP_SIZE(right);
13111     /* if unsigned or not an integral type */
13112     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13113       while (size--)
13114         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13115     } else {
13116       /* we need to extend the sign :( */
13117
13118       if(size == 1) {
13119         /* Save one instruction of casting char to int */
13120         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13121         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13122         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
13123       } else {
13124         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13125
13126         if(offset)
13127           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13128         else
13129           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13130         
13131         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13132
13133         while (size--)
13134           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13135       }
13136     }
13137
13138 release:
13139     pic16_freeAsmop(right,NULL,ic,TRUE);
13140     pic16_freeAsmop(result,NULL,ic,TRUE);
13141
13142 }
13143
13144 /*-----------------------------------------------------------------*/
13145 /* genDjnz - generate decrement & jump if not zero instrucion      */
13146 /*-----------------------------------------------------------------*/
13147 static int genDjnz (iCode *ic, iCode *ifx)
13148 {
13149     symbol *lbl, *lbl1;
13150     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13151
13152     if (!ifx)
13153         return 0;
13154     
13155     /* if the if condition has a false label
13156        then we cannot save */
13157     if (IC_FALSE(ifx))
13158         return 0;
13159
13160     /* if the minus is not of the form 
13161        a = a - 1 */
13162     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13163         !IS_OP_LITERAL(IC_RIGHT(ic)))
13164         return 0;
13165
13166     if (operandLitValue(IC_RIGHT(ic)) != 1)
13167         return 0;
13168
13169     /* if the size of this greater than one then no
13170        saving */
13171     if (getSize(operandType(IC_RESULT(ic))) > 1)
13172         return 0;
13173
13174     /* otherwise we can save BIG */
13175     lbl = newiTempLabel(NULL);
13176     lbl1= newiTempLabel(NULL);
13177
13178     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13179     
13180     if (IS_AOP_PREG(IC_RESULT(ic))) {
13181         pic16_emitcode("dec","%s",
13182                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13183         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13184         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13185     } else {    
13186
13187
13188       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13189       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13190
13191       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13192       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13193
13194     }
13195     
13196     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13197     ifx->generated = 1;
13198     return 1;
13199 }
13200
13201 /*-----------------------------------------------------------------*/
13202 /* genReceive - generate code for a receive iCode                  */
13203 /*-----------------------------------------------------------------*/
13204 static void genReceive (iCode *ic)
13205 {    
13206
13207   FENTRY;
13208
13209 #if 0
13210   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13211         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13212 #endif
13213 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13214
13215   if (isOperandInFarSpace(IC_RESULT(ic))
13216       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13217           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13218
13219     int size = getSize(operandType(IC_RESULT(ic)));
13220     int offset =  pic16_fReturnSizePic - size;
13221
13222       assert( 0 );
13223       while (size--) {
13224         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13225                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13226                       offset++;
13227         }
13228
13229       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13230
13231       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13232       size = AOP_SIZE(IC_RESULT(ic));
13233       offset = 0;
13234       while (size--) {
13235         pic16_emitcode ("pop","acc");
13236         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13237       }
13238   } else {
13239     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13240     _G.accInUse++;
13241     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13242     _G.accInUse--;
13243
13244     /* set pseudo stack pointer to where it should be - dw*/
13245     GpsuedoStkPtr = ic->parmBytes;
13246
13247     /* setting GpsuedoStkPtr has side effects here: */
13248     assignResultValue(IC_RESULT(ic), 0);
13249   }
13250
13251   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13252 }
13253
13254 /*-----------------------------------------------------------------*/
13255 /* genDummyRead - generate code for dummy read of volatiles        */
13256 /*-----------------------------------------------------------------*/
13257 static void
13258 genDummyRead (iCode * ic)
13259 {
13260   operand *op;
13261   int i;
13262
13263   op = IC_RIGHT(ic);
13264   if (op && IS_SYMOP(op)) {
13265     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13266       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13267       return;
13268     }
13269     pic16_aopOp (op, ic, FALSE);
13270     for (i=0; i < AOP_SIZE(op); i++) {
13271       // may need to protect this from the peepholer -- this is not nice but works...
13272       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13273       pic16_mov2w (AOP(op),i);
13274       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13275     } // for i
13276     pic16_freeAsmop (op, NULL, ic, TRUE);
13277   } else if (op) {
13278     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13279   } // if
13280 }
13281
13282 /*-----------------------------------------------------------------*/
13283 /* genpic16Code - generate code for pic16 based controllers        */
13284 /*-----------------------------------------------------------------*/
13285 /*
13286  * At this point, ralloc.c has gone through the iCode and attempted
13287  * to optimize in a way suitable for a PIC. Now we've got to generate
13288  * PIC instructions that correspond to the iCode.
13289  *
13290  * Once the instructions are generated, we'll pass through both the
13291  * peep hole optimizer and the pCode optimizer.
13292  *-----------------------------------------------------------------*/
13293
13294 void genpic16Code (iCode *lic)
13295 {
13296   iCode *ic;
13297   int cln = 0;
13298
13299     lineHead = lineCurr = NULL;
13300
13301     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13302     pic16_addpBlock(pb);
13303
13304 #if 0
13305     /* if debug information required */
13306     if (options.debug && currFunc) {
13307       if (currFunc) {
13308         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13309       }
13310     }
13311 #endif
13312
13313     for (ic = lic ; ic ; ic = ic->next ) {
13314
13315       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13316       if ( cln != ic->lineno ) {
13317         if ( options.debug ) {
13318           debugFile->writeCLine (ic);
13319         }
13320         
13321         if(!options.noCcodeInAsm) {
13322           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13323               printCLine(ic->filename, ic->lineno)));
13324         }
13325
13326         cln = ic->lineno ;
13327       }
13328         
13329       if(options.iCodeInAsm) {
13330         char *l;
13331
13332           /* insert here code to print iCode as comment */
13333           l = Safe_strdup(printILine(ic));
13334           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13335       }
13336         
13337       /* if the result is marked as
13338        * spilt and rematerializable or code for
13339        * this has already been generated then
13340        * do nothing */
13341       if (resultRemat(ic) || ic->generated ) 
13342         continue ;
13343         
13344       /* depending on the operation */
13345       switch (ic->op) {
13346         case '!' :
13347           pic16_genNot(ic);
13348           break;
13349             
13350         case '~' :
13351           pic16_genCpl(ic);
13352           break;
13353             
13354         case UNARYMINUS:
13355           genUminus (ic);
13356           break;
13357             
13358         case IPUSH:
13359           genIpush (ic);
13360           break;
13361             
13362         case IPOP:
13363           /* IPOP happens only when trying to restore a 
13364            * spilt live range, if there is an ifx statement
13365            * following this pop then the if statement might
13366            * be using some of the registers being popped which
13367            * would destroy the contents of the register so
13368            * we need to check for this condition and handle it */
13369            if (ic->next
13370              && ic->next->op == IFX
13371              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13372                genIfx (ic->next,ic);
13373           else
13374             genIpop (ic);
13375           break; 
13376             
13377         case CALL:
13378           genCall (ic);
13379           break;
13380             
13381         case PCALL:
13382           genPcall (ic);
13383           break;
13384             
13385         case FUNCTION:
13386           genFunction (ic);
13387           break;
13388             
13389         case ENDFUNCTION:
13390           genEndFunction (ic);
13391           break;
13392             
13393         case RETURN:
13394           genRet (ic);
13395           break;
13396             
13397         case LABEL:
13398           genLabel (ic);
13399           break;
13400             
13401         case GOTO:
13402           genGoto (ic);
13403           break;
13404             
13405         case '+' :
13406           pic16_genPlus (ic) ;
13407           break;
13408             
13409         case '-' :
13410           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13411             pic16_genMinus (ic);
13412           break;
13413
13414         case '*' :
13415           genMult (ic);
13416           break;
13417             
13418         case '/' :
13419           genDiv (ic) ;
13420           break;
13421             
13422         case '%' :
13423           genMod (ic);
13424           break;
13425             
13426         case '>' :
13427           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13428           break;
13429             
13430         case '<' :
13431           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13432           break;
13433             
13434         case LE_OP:
13435         case GE_OP:
13436         case NE_OP:
13437           /* note these two are xlated by algebraic equivalence
13438            * during parsing SDCC.y */
13439           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13440             "got '>=' or '<=' shouldn't have come here");
13441           break;
13442
13443         case EQ_OP:
13444           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13445           break;            
13446             
13447         case AND_OP:
13448           genAndOp (ic);
13449           break;
13450             
13451         case OR_OP:
13452           genOrOp (ic);
13453           break;
13454             
13455         case '^' :
13456           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13457           break;
13458             
13459         case '|' :
13460           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13461           break;
13462             
13463         case BITWISEAND:
13464           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13465           break;
13466             
13467         case INLINEASM:
13468           genInline (ic);
13469           break;
13470             
13471         case RRC:
13472           genRRC (ic);
13473           break;
13474             
13475         case RLC:
13476           genRLC (ic);
13477           break;
13478             
13479         case GETHBIT:
13480           genGetHbit (ic);
13481           break;
13482             
13483         case LEFT_OP:
13484           genLeftShift (ic);
13485           break;
13486             
13487         case RIGHT_OP:
13488           genRightShift (ic);
13489           break;
13490             
13491         case GET_VALUE_AT_ADDRESS:
13492           genPointerGet(ic);
13493           break;
13494             
13495         case '=' :
13496           if (POINTER_SET(ic))
13497             genPointerSet(ic);
13498           else
13499             genAssign(ic);
13500           break;
13501             
13502         case IFX:
13503           genIfx (ic,NULL);
13504           break;
13505             
13506         case ADDRESS_OF:
13507           genAddrOf (ic);
13508           break;
13509             
13510         case JUMPTABLE:
13511           genJumpTab (ic);
13512           break;
13513             
13514         case CAST:
13515           genCast (ic);
13516           break;
13517             
13518         case RECEIVE:
13519           genReceive(ic);
13520           break;
13521             
13522         case SEND:
13523           addSet(&_G.sendSet,ic);
13524           break;
13525
13526         case DUMMY_READ_VOLATILE:
13527           genDummyRead (ic);
13528           break;
13529
13530         default :
13531           ic = ic;
13532       }
13533     }
13534
13535
13536     /* now we are ready to call the
13537        peep hole optimizer */
13538     if (!options.nopeep)
13539       peepHole (&lineHead);
13540
13541     /* now do the actual printing */
13542     printLine (lineHead, codeOutFile);
13543
13544 #ifdef PCODE_DEBUG
13545     DFPRINTF((stderr,"printing pBlock\n\n"));
13546     pic16_printpBlock(stdout,pb);
13547 #endif
13548
13549     return;
13550 }
13551