* src/pic16/gen.{c,h}: s/mov2f/pic16_mov2f made public
[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 mov2fp(pCodeOp *dst, asmop *src, int offset);
72 static pCodeOp *pic16_popRegFromIdx(int rIdx);
73
74 //static int aopIdx (asmop *aop, int offset);
75
76 int pic16_labelOffset=0;
77 extern int pic16_debug_verbose;
78 #if !(USE_GENERIC_SIGNED_SHIFT)
79 static int optimized_for_speed = 0;
80 #endif
81 /*
82   hack hack
83
84 */
85
86 extern set *externs;
87
88 /* max_key keeps track of the largest label number used in 
89    a function. This is then used to adjust the label offset
90    for the next function.
91 */
92 static int max_key=0;
93 static int GpsuedoStkPtr=0;
94
95 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
96
97 unsigned int pic16aopLiteral (value *val, int offset);
98 const char *pic16_AopType(short type);
99 static iCode *ifxForOp ( operand *op, iCode *ic );
100
101 void pic16_pushpCodeOp(pCodeOp *pcop);
102 void pic16_poppCodeOp(pCodeOp *pcop);
103
104 static bool is_LitOp(operand *op);
105 static bool is_LitAOp(asmop *aop);
106
107
108 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
109
110 /* set the following macro to 1 to enable passing the
111  * first byte of functions parameters via WREG */
112 #define USE_WREG_IN_FUNC_PARAMS 0
113
114
115 /* this is the down and dirty file with all kinds of 
116    kludgy & hacky stuff. This is what it is all about
117    CODE GENERATION for a specific MCU . some of the
118    routines may be reusable, will have to see */
119
120 static char *zero = "#0x00";
121 static char *one  = "#0x01";
122 //static char *spname = "sp";
123
124
125 /*
126  * Function return value policy (MSB-->LSB):
127  *  8 bits      -> WREG
128  * 16 bits      -> PRODL:WREG
129  * 24 bits      -> PRODH:PRODL:WREG
130  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
131  * >32 bits     -> on stack, and FSR0 points to the beginning
132  *
133  */
134  
135
136 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
137 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
138 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
139 static char **fReturn = fReturnpic16;
140
141 static char *accUse[] = {"WREG"};
142
143 //static short rbank = -1;
144
145 static struct {
146     short r0Pushed;
147     short r1Pushed;
148     short fsr0Pushed;
149     short accInUse;
150     short inLine;
151     short debugLine;
152     short nRegsSaved;
153     short ipushRegs;
154     set *sendSet;
155     set *stackRegSet;
156     int usefastretfie;
157     bitVect *fregsUsed;                 /* registers used in function */
158     bitVect *sregsAlloc;
159     set *sregsAllocSet;                 /* registers used to store stack variables */
160     int stack_lat;                      /* stack offset latency */
161     int resDirect;
162     int useWreg;                        /* flag when WREG is used to pass function parameter */
163 } _G;
164
165 extern int pic16_ptrRegReq ;
166 extern int pic16_nRegs;
167 extern FILE *codeOutFile;
168 //static void saverbank (int, iCode *,bool);
169
170 static lineNode *lineHead = NULL;
171 static lineNode *lineCurr = NULL;
172
173 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
174 0xE0, 0xC0, 0x80, 0x00};
175 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
176 0x07, 0x03, 0x01, 0x00};
177
178 static  pBlock *pb;
179
180 /*-----------------------------------------------------------------*/
181 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
182 /*                 exponent of 2 is returned, otherwise -1 is      */
183 /*                 returned.                                       */
184 /* note that this is similar to the function `powof2' in SDCCsymt  */
185 /* if(n == 2^y)                                                    */
186 /*   return y;                                                     */
187 /* return -1;                                                      */
188 /*-----------------------------------------------------------------*/
189 int pic16_my_powof2 (unsigned long num)
190 {
191   if(num) {
192     if( (num & (num-1)) == 0) {
193       int nshifts = -1;
194       while(num) {
195         num>>=1;
196         nshifts++;
197       }
198       return nshifts;
199     }
200   }
201
202   return -1;
203 }
204
205 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
206 {
207   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
208                        line_no,
209                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
210                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
211                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
212                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
213                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
214                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
215                        ((result) ? AOP_SIZE(result) : 0));
216 }
217
218 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
219 {
220
221   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
222                        line_no,
223                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
224                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
225                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
226                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
227                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
228                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
229
230 }
231
232 void pic16_emitpcomment (char *fmt, ...)
233 {
234     va_list ap;
235     char lb[INITIAL_INLINEASM];  
236     char *lbp = lb;
237
238     va_start(ap,fmt);   
239
240     lb[0] = ';';
241     vsprintf(lb+1,fmt,ap);
242
243     while (isspace(*lbp)) lbp++;
244
245     if (lbp && *lbp) 
246         lineCurr = (lineCurr ?
247                     connectLine(lineCurr,newLineNode(lb)) :
248                     (lineHead = newLineNode(lb)));
249     lineCurr->isInline = _G.inLine;
250     lineCurr->isDebug  = _G.debugLine;
251
252     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
253     va_end(ap);
254
255 //      fprintf(stderr, "%s\n", lb);
256 }
257
258 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
259 {
260     va_list ap;
261     char lb[INITIAL_INLINEASM];  
262     char *lbp = lb;
263
264     if(!pic16_debug_verbose)
265       return;
266
267     va_start(ap,fmt);   
268
269     if (inst && *inst) {
270         if (fmt && *fmt)
271             sprintf(lb,"%s\t",inst);
272         else
273             sprintf(lb,"%s",inst);
274         vsprintf(lb+(strlen(lb)),fmt,ap);
275     }  else
276         vsprintf(lb,fmt,ap);
277
278     while (isspace(*lbp)) lbp++;
279
280     if (lbp && *lbp) 
281         lineCurr = (lineCurr ?
282                     connectLine(lineCurr,newLineNode(lb)) :
283                     (lineHead = newLineNode(lb)));
284     lineCurr->isInline = _G.inLine;
285     lineCurr->isDebug  = _G.debugLine;
286
287     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
288     va_end(ap);
289
290 //      fprintf(stderr, "%s\n", lb);
291 }
292
293
294
295 void pic16_emitpLabel(int key)
296 {
297   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
298 }
299
300 void pic16_emitpLabelFORCE(int key)
301 {
302   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
303 }
304
305 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
306 {
307
308   if(pcop)
309     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
310   else
311     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
312 }
313
314 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
315 {
316   if(pcop)
317     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
318   else
319     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
320 }
321   
322 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
323 {
324
325   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
326
327 }
328
329
330 #if 1
331 #define pic16_emitcode  DEBUGpic16_emitcode
332 #else
333 /*-----------------------------------------------------------------*/
334 /* pic16_emitcode - writes the code into a file : for now it is simple    */
335 /*-----------------------------------------------------------------*/
336 void pic16_emitcode (char *inst,char *fmt, ...)
337 {
338     va_list ap;
339     char lb[INITIAL_INLINEASM];  
340     char *lbp = lb;
341
342     va_start(ap,fmt);   
343
344     if (inst && *inst) {
345         if (fmt && *fmt)
346             sprintf(lb,"%s\t",inst);
347         else
348             sprintf(lb,"%s",inst);
349         vsprintf(lb+(strlen(lb)),fmt,ap);
350     }  else
351         vsprintf(lb,fmt,ap);
352
353     while (isspace(*lbp)) lbp++;
354
355     if (lbp && *lbp) 
356         lineCurr = (lineCurr ?
357                     connectLine(lineCurr,newLineNode(lb)) :
358                     (lineHead = newLineNode(lb)));
359     lineCurr->isInline = _G.inLine;
360     lineCurr->isDebug  = _G.debugLine;
361
362 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
363
364 //    if(pic16_debug_verbose)
365 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
366
367     va_end(ap);
368 }
369 #endif
370
371
372 /*-----------------------------------------------------------------*/
373 /* pic16_emitDebuggerSymbol - associate the current code location  */
374 /*   with a debugger symbol                                        */
375 /*-----------------------------------------------------------------*/
376 void
377 pic16_emitDebuggerSymbol (char * debugSym)
378 {
379   _G.debugLine = 1;
380   pic16_emitcode (";", "%s ==.", debugSym);
381   _G.debugLine = 0;
382 }
383
384
385 /*-----------------------------------------------------------------*/
386 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
387 /*-----------------------------------------------------------------*/
388 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
389 {
390 //    bool r0iu = FALSE , r1iu = FALSE;
391 //    bool r0ou = FALSE , r1ou = FALSE;
392     bool fsr0iu = FALSE, fsr0ou;
393     bool fsr2iu = FALSE, fsr2ou;
394     
395     fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
396
397     
398     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
399     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
400     
401     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
402     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
403
404     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
405         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
406         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
407     }
408
409     if(!fsr0iu && !fsr0ou) {
410         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
411         (*aopp)->type = AOP_FSR0;
412
413         fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
414         
415       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
416     }
417
418 #if 0
419     /* no usage of FSR2 */
420     if(!fsr2iu && !fsr2ou) {
421         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
422         (*aopp)->type = AOP_FSR2;
423
424       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
425     }
426 #endif
427         
428     /* now we know they both have usage */
429     /* if fsr0 not used in this instruction */
430     if (!fsr0iu) {
431         if (!_G.fsr0Pushed) {
432                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
433                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
434                 _G.fsr0Pushed++;
435         }
436
437         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
438         (*aopp)->type = AOP_FSR0;
439
440 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
441
442       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
443     }
444         
445
446     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
447     assert( 0 );
448
449     return NULL;
450 #if 0
451     /* the logic: if r0 & r1 used in the instruction
452     then we are in trouble otherwise */
453
454     /* first check if r0 & r1 are used by this
455     instruction, in which case we are in trouble */
456     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
457         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
458     {
459         goto endOfWorld;      
460     }
461
462     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
463     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
464
465     /* if no usage of r0 then return it */
466     if (!r0iu && !r0ou) {
467         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
468         (*aopp)->type = AOP_R0; 
469         
470         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
471     }
472
473     /* if no usage of r1 then return it */
474     if (!r1iu && !r1ou) {
475         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
476         (*aopp)->type = AOP_R1;
477
478         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
479     }    
480
481     /* now we know they both have usage */
482     /* if r0 not used in this instruction */
483     if (!r0iu) {
484         /* push it if not already pushed */
485         if (!_G.r0Pushed) {
486           //pic16_emitcode ("push","%s",
487           //          pic16_regWithIdx(R0_IDX)->dname);
488             _G.r0Pushed++ ;
489         }
490         
491         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
492         (*aopp)->type = AOP_R0;
493
494         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
495     }
496
497     /* if r1 not used then */
498
499     if (!r1iu) {
500         /* push it if not already pushed */
501         if (!_G.r1Pushed) {
502           //pic16_emitcode ("push","%s",
503           //          pic16_regWithIdx(R1_IDX)->dname);
504             _G.r1Pushed++ ;
505         }
506         
507         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
508         (*aopp)->type = AOP_R1;
509         return pic16_regWithIdx(R1_IDX);
510     }
511
512 endOfWorld :
513     /* I said end of world but not quite end of world yet */
514     /* if this is a result then we can push it on the stack*/
515     if (result) {
516         (*aopp)->type = AOP_STK;    
517         return NULL;
518     }
519
520     /* other wise this is true end of the world */
521     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
522            "getFreePtr should never reach here");
523     exit(0);
524 #endif
525 }
526
527 /*-----------------------------------------------------------------*/
528 /* newAsmop - creates a new asmOp                                  */
529 /*-----------------------------------------------------------------*/
530 static asmop *newAsmop (short type)
531 {
532     asmop *aop;
533
534     aop = Safe_calloc(1,sizeof(asmop));
535     aop->type = type;
536     return aop;
537 }
538
539 static void genSetDPTR(int n)
540 {
541     if (!n)
542     {
543         pic16_emitcode(";", "Select standard DPTR");
544         pic16_emitcode("mov", "dps, #0x00");
545     }
546     else
547     {
548         pic16_emitcode(";", "Select alternate DPTR");
549         pic16_emitcode("mov", "dps, #0x01");
550     }
551 }
552
553 /*-----------------------------------------------------------------*/
554 /* resolveIfx - converts an iCode ifx into a form more useful for  */
555 /*              generating code                                    */
556 /*-----------------------------------------------------------------*/
557 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
558 {
559   FENTRY2;
560   
561 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
562
563   if(!resIfx) 
564     return;
565
566
567   resIfx->condition = 1;    /* assume that the ifx is true */
568   resIfx->generated = 0;    /* indicate that the ifx has not been used */
569
570   if(!ifx) {
571     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
572
573 #if 1
574     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
575                         __FUNCTION__,__LINE__,resIfx->lbl->key);
576 #endif
577
578   } else {
579     if(IC_TRUE(ifx)) {
580       resIfx->lbl = IC_TRUE(ifx);
581     } else {
582       resIfx->lbl = IC_FALSE(ifx);
583       resIfx->condition = 0;
584     }
585
586 #if 1
587     if(IC_TRUE(ifx)) 
588       DEBUGpic16_emitcode("; +++","ifx true is non-null");
589     else
590       DEBUGpic16_emitcode("; +++","ifx true is null");
591     if(IC_FALSE(ifx)) 
592       DEBUGpic16_emitcode("; +++","ifx false is non-null");
593     else
594       DEBUGpic16_emitcode("; +++","ifx false is null");
595 #endif
596   }
597
598   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
599
600 }
601 #if 0
602 /*-----------------------------------------------------------------*/
603 /* pointerCode - returns the code for a pointer type               */
604 /*-----------------------------------------------------------------*/
605 static int pointerCode (sym_link *etype)
606 {
607
608     return PTR_TYPE(SPEC_OCLS(etype));
609
610 }
611 #endif
612
613 /*-----------------------------------------------------------------*/
614 /* aopForSym - for a true symbol                                   */
615 /*-----------------------------------------------------------------*/
616 static asmop *aopForSym (iCode *ic, operand *op, bool result)
617 {
618     symbol *sym=OP_SYMBOL(op);
619     asmop *aop;
620     memmap *space= SPEC_OCLS(sym->etype);
621
622     FENTRY2;
623     
624     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
625     
626 //    sym = OP_SYMBOL(op);
627
628     /* if already has one */
629     if (sym->aop) {
630             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
631         return sym->aop;
632     }
633
634 #if 0
635     /* if symbol was initially placed onStack then we must re-place it
636      * to direct memory, since pic16 does not have a specific stack */
637     if(sym->onStack) {
638         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
639     }
640 #endif
641
642
643 #if 0
644     if(sym->iaccess) {
645       if(space->paged) {
646         fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
647
648         sym->aop = aop = newAsmop (AOP_PAGED);
649         aop->aopu.aop_dir = sym->rname ;
650         aop->size = getSize(sym->type);
651         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
652         pic16_allocDirReg( IC_LEFT(ic) );
653         return aop;
654       }
655       assert( 0 );
656     }
657 #endif
658     
659 #if 1
660     /* assign depending on the storage class */
661     /* if it is on the stack or indirectly addressable */
662     /* space we need to assign either r0 or r1 to it   */    
663     if (sym->onStack)   // || sym->iaccess)
664     {
665       pCodeOp *pcop[4];
666       int i;
667       
668         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
669                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
670         
671         /* acquire a temporary register -- it is saved in function */
672
673         sym->aop = aop = newAsmop(AOP_STA);
674         aop->aopu.stk.stk = sym->stack;
675         aop->size = getSize(sym->type);
676
677
678         DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
679         if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
680           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
681 //          pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
682           
683           for(i=0;i<aop->size;i++)
684             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
685             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
686         } else
687         if(1 && ic->op == SEND) {
688
689           /* if SEND do the send here */
690           _G.resDirect = 1;
691         } else {
692           for(i=0;i<aop->size;i++) {
693             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
694             _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
695           }
696         }
697
698
699 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
700
701 #if 1
702         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
703
704         // we do not need to load the value if it is to be defined...
705         if (result) return aop;
706
707         if(_G.accInUse) {
708                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
709         }
710         
711         for(i=0;i<aop->size;i++) {
712
713           /* initialise for stack access via frame pointer */
714           // operands on stack are accessible via "FSR2 + index" with index
715           // starting at 2 for arguments and growing from 0 downwards for
716           // local variables (index == 0 is not assigned so we add one here)
717           {
718             int soffs = sym->stack;
719             if (soffs <= 0) {
720               assert (soffs < 0);
721               soffs++;
722             } // if
723
724             if(1 && ic->op == SEND) {
725               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
726               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
727                     pic16_popCopyReg( pic16_frame_plusw ),
728                     pic16_popCopyReg(pic16_stack_postdec )));
729             } else {
730               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
731               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
732                   pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
733             }
734           }
735         }
736         
737         if(_G.accInUse) {
738                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
739         }
740         
741         return (aop);
742 #endif
743
744 #if 0
745         /* now assign the address of the variable to 
746         the pointer register */
747         if (aop->type != AOP_STK) {
748
749             if (sym->onStack) {
750                     if ( _G.accInUse )
751                         pic16_emitcode("push","acc");
752
753                     pic16_emitcode("mov","a,_bp");
754                     pic16_emitcode("add","a,#0x%02x",
755                              ((sym->stack < 0) ?
756                               ((char)(sym->stack - _G.nRegsSaved )) :
757                               ((char)sym->stack)) & 0xff);
758                     pic16_emitcode("mov","%s,a",
759                              aop->aopu.aop_ptr->name);
760
761                     if ( _G.accInUse )
762                         pic16_emitcode("pop","acc");
763             } else
764                 pic16_emitcode("mov","%s,#%s",
765                          aop->aopu.aop_ptr->name,
766                          sym->rname);
767             aop->paged = space->paged;
768         } else
769             aop->aopu.aop_stk = sym->stack;
770         return aop;
771 #endif
772
773     }
774 #endif
775
776 #if 0
777     if (sym->onStack && options.stack10bit)
778     {
779         /* It's on the 10 bit stack, which is located in
780          * far data space.
781          */
782          
783       //DEBUGpic16_emitcode(";","%d",__LINE__);
784
785         if ( _G.accInUse )
786                 pic16_emitcode("push","acc");
787
788         pic16_emitcode("mov","a,_bp");
789         pic16_emitcode("add","a,#0x%02x",
790                  ((sym->stack < 0) ?
791                    ((char)(sym->stack - _G.nRegsSaved )) :
792                    ((char)sym->stack)) & 0xff);
793         
794         genSetDPTR(1);
795         pic16_emitcode ("mov","dpx1,#0x40");
796         pic16_emitcode ("mov","dph1,#0x00");
797         pic16_emitcode ("mov","dpl1, a");
798         genSetDPTR(0);
799         
800         if ( _G.accInUse )
801             pic16_emitcode("pop","acc");
802             
803         sym->aop = aop = newAsmop(AOP_DPTR2);
804         aop->size = getSize(sym->type); 
805         return aop;
806     }
807 #endif
808
809 #if 1
810     /* special case for a function */
811     if (IS_FUNC(sym->type)) {   
812         sym->aop = aop = newAsmop(AOP_PCODE);
813         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
814         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
815         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
816         PCOI(aop->aopu.pcop)->index = 0;
817         aop->size = FPTRSIZE; 
818         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
819         return aop;
820     }
821 #endif
822
823
824
825     //DEBUGpic16_emitcode(";","%d",__LINE__);
826     /* if in bit space */
827     if (IN_BITSPACE(space)) {
828         sym->aop = aop = newAsmop (AOP_CRY);
829         aop->aopu.aop_dir = sym->rname ;
830         aop->size = getSize(sym->type);
831         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
832         return aop;
833     }
834     /* if it is in direct space */
835     if (IN_DIRSPACE(space)) {
836         sym->aop = aop = newAsmop (AOP_DIR);
837         aop->aopu.aop_dir = sym->rname ;
838         aop->size = getSize(sym->type);
839         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
840         pic16_allocDirReg( IC_LEFT(ic) );
841         return aop;
842     }
843
844
845     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
846         sym->aop = aop = newAsmop (AOP_DIR);
847         aop->aopu.aop_dir = sym->rname ;
848         aop->size = getSize(sym->type);
849         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
850         pic16_allocDirReg( IC_LEFT(ic) );
851         return aop;
852     }
853
854
855     /* only remaining is far space */
856     sym->aop = aop = newAsmop(AOP_PCODE);
857
858 /* change the next if to 1 to revert to good old immediate code */
859         if(IN_CODESPACE(space)) {
860                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
861                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
862                 PCOI(aop->aopu.pcop)->index = 0;
863         } else {
864                 /* try to allocate via direct register */
865                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
866 //              aop->size = getSize( sym->type );
867         }
868
869         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
870                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
871
872 #if 0
873         if(!pic16_allocDirReg (IC_LEFT(ic)))
874                 return NULL;
875 #endif
876
877         if(IN_DIRSPACE( space ))
878                 aop->size = PTRSIZE;
879         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
880                 aop->size = FPTRSIZE;
881         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
882         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
883         else if(sym->onStack) {
884                 aop->size = PTRSIZE;
885         } else {
886           if(SPEC_SCLS(sym->etype) == S_PDATA) {
887             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
888             aop->size = FPTRSIZE;
889           } else
890                 assert( 0 );
891         }
892
893     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
894
895     /* if it is in code space */
896     if (IN_CODESPACE(space))
897         aop->code = 1;
898
899     return aop;     
900 }
901
902 /*-----------------------------------------------------------------*/
903 /* aopForRemat - rematerialzes an object                           */
904 /*-----------------------------------------------------------------*/
905 static asmop *aopForRemat (operand *op) // x symbol *sym)
906 {
907   symbol *sym = OP_SYMBOL(op);
908   operand *refop;
909   iCode *ic = NULL, *oldic;
910   asmop *aop = newAsmop(AOP_PCODE);
911   int val = 0;
912   int offset = 0;
913   int viaimmd=0;
914
915     FENTRY2;
916     
917         ic = sym->rematiCode;
918
919         if(IS_OP_POINTER(op)) {
920                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
921         }
922
923         for (;;) {
924                 oldic = ic;
925
926 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
927         
928                 if (ic->op == '+') {
929                         val += (int) operandLitValue(IC_RIGHT(ic));
930                 } else if (ic->op == '-') {
931                         val -= (int) operandLitValue(IC_RIGHT(ic));
932                 } else
933                         break;
934                 
935                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
936         }
937
938         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
939         refop = IC_LEFT(ic);
940
941         if(!op->isaddr)viaimmd++; else viaimmd=0;
942                 
943 /* set the following if to 1 to revert to good old immediate code */
944         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
945                 || viaimmd) {
946
947                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
948
949                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
950
951 #if 0
952                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
953 #else
954                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
955 #endif
956
957                 PCOI(aop->aopu.pcop)->index = val;
958                 
959                 aop->size = getSize( sym->type );
960         } else {
961                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
962
963                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
964                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
965
966                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
967         }
968
969
970         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
971                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
972 #if 0
973                 val, IS_PTR_CONST(operandType(op)));
974 #else
975                 val, IS_CODEPTR(operandType(op)));
976 #endif
977
978 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
979
980         pic16_allocDirReg (IC_LEFT(ic));
981
982         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
983                 aop->code = 1;
984
985   return aop;        
986 }
987
988 #if 0
989 static int aopIdx (asmop *aop, int offset)
990 {
991   if(!aop)
992     return -1;
993
994   if(aop->type !=  AOP_REG)
995     return -2;
996         
997   return aop->aopu.aop_reg[offset]->rIdx;
998
999 }
1000 #endif
1001
1002 /*-----------------------------------------------------------------*/
1003 /* regsInCommon - two operands have some registers in common       */
1004 /*-----------------------------------------------------------------*/
1005 static bool regsInCommon (operand *op1, operand *op2)
1006 {
1007     symbol *sym1, *sym2;
1008     int i;
1009
1010     /* if they have registers in common */
1011     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1012         return FALSE ;
1013
1014     sym1 = OP_SYMBOL(op1);
1015     sym2 = OP_SYMBOL(op2);
1016
1017     if (sym1->nRegs == 0 || sym2->nRegs == 0)
1018         return FALSE ;
1019
1020     for (i = 0 ; i < sym1->nRegs ; i++) {
1021         int j;
1022         if (!sym1->regs[i])
1023             continue ;
1024
1025         for (j = 0 ; j < sym2->nRegs ;j++ ) {
1026             if (!sym2->regs[j])
1027                 continue ;
1028
1029             if (sym2->regs[j] == sym1->regs[i])
1030                 return TRUE ;
1031         }
1032     }
1033
1034     return FALSE ;
1035 }
1036
1037 /*-----------------------------------------------------------------*/
1038 /* operandsEqu - equivalent                                        */
1039 /*-----------------------------------------------------------------*/
1040 static bool operandsEqu ( operand *op1, operand *op2)
1041 {
1042     symbol *sym1, *sym2;
1043
1044     /* if they not symbols */
1045     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1046         return FALSE;
1047
1048     sym1 = OP_SYMBOL(op1);
1049     sym2 = OP_SYMBOL(op2);
1050
1051     /* if both are itemps & one is spilt
1052        and the other is not then false */
1053     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1054         sym1->isspilt != sym2->isspilt )
1055         return FALSE ;
1056
1057     /* if they are the same */
1058     if (sym1 == sym2)
1059         return TRUE ;
1060
1061     if (sym1->rname[0] && sym2->rname[0]
1062         && strcmp (sym1->rname, sym2->rname) == 0)
1063         return TRUE;
1064
1065
1066     /* if left is a tmp & right is not */
1067     if (IS_ITEMP(op1)  && 
1068         !IS_ITEMP(op2) &&
1069         sym1->isspilt  &&
1070         (sym1->usl.spillLoc == sym2))
1071         return TRUE;
1072
1073     if (IS_ITEMP(op2)  && 
1074         !IS_ITEMP(op1) &&
1075         sym2->isspilt  &&
1076         sym1->level > 0 &&
1077         (sym2->usl.spillLoc == sym1))
1078         return TRUE ;
1079
1080     return FALSE ;
1081 }
1082
1083 /*-----------------------------------------------------------------*/
1084 /* pic16_sameRegs - two asmops have the same registers                   */
1085 /*-----------------------------------------------------------------*/
1086 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1087 {
1088     int i;
1089
1090     if (aop1 == aop2)
1091         return TRUE ;
1092
1093     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1094                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1095
1096     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1097
1098     if (aop1->type != AOP_REG ||
1099         aop2->type != AOP_REG )
1100         return FALSE ;
1101
1102     /* This is a bit too restrictive if one is a subset of the other...
1103     if (aop1->size != aop2->size )
1104         return FALSE ;
1105     */
1106
1107     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1108 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1109
1110 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1111         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1112             return FALSE ;
1113     }
1114
1115     return TRUE ;
1116 }
1117
1118 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1119 {
1120     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1121                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1122
1123     if(aop1 == aop2)return TRUE;
1124     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1125       
1126       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1127     
1128   return TRUE;
1129 }
1130
1131
1132 /*-----------------------------------------------------------------*/
1133 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1134 /*-----------------------------------------------------------------*/
1135 void pic16_aopOp (operand *op, iCode *ic, bool result)
1136 {
1137     asmop *aop;
1138     symbol *sym;
1139     int i;
1140
1141     if (!op)
1142         return ;
1143
1144     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1145
1146     /* if this a literal */
1147     if (IS_OP_LITERAL(op)) {
1148         op->aop = aop = newAsmop(AOP_LIT);
1149         aop->aopu.aop_lit = op->operand.valOperand;
1150         aop->size = getSize(operandType(op));
1151         return;
1152     }
1153
1154     {
1155       sym_link *type = operandType(op);
1156 #if 0
1157       if(IS_PTR_CONST(type))
1158 #else
1159       if(IS_CODEPTR(type))
1160 #endif
1161         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1162     }
1163
1164     /* if already has a asmop then continue */
1165     if (op->aop)
1166         return ;
1167
1168     /* if the underlying symbol has a aop */
1169     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1170       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1171         op->aop = OP_SYMBOL(op)->aop;
1172         return;
1173     }
1174
1175     /* if this is a true symbol */
1176     if (IS_TRUE_SYMOP(op)) {    
1177         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1178       op->aop = aopForSym(ic, op, result);
1179       return ;
1180     }
1181
1182     /* this is a temporary : this has
1183     only four choices :
1184     a) register
1185     b) spillocation
1186     c) rematerialize 
1187     d) conditional   
1188     e) can be a return use only */
1189
1190     sym = OP_SYMBOL(op);
1191
1192     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1193     /* if the type is a conditional */
1194     if (sym->regType == REG_CND) {
1195         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1196         aop->size = 0;
1197         return;
1198     }
1199
1200     /* if it is spilt then two situations
1201     a) is rematerialize 
1202     b) has a spill location */
1203     if (sym->isspilt || sym->nRegs == 0) {
1204
1205 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1206       DEBUGpic16_emitcode(";","%d",__LINE__);
1207         /* rematerialize it NOW */
1208         if (sym->remat) {
1209
1210             sym->aop = op->aop = aop = aopForRemat (op);
1211 //            aop->size = getSize(sym->type);
1212 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1213             return;
1214         }
1215
1216 #if 1
1217         if (sym->accuse) {
1218             int i;
1219             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1220             aop->size = getSize(sym->type);
1221             for ( i = 0 ; i < 1 ; i++ ) {
1222                 aop->aopu.aop_str[i] = accUse[i];
1223 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1224             }
1225             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1226             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1227             return;  
1228         }
1229 #endif
1230
1231 #if 1
1232         if (sym->ruonly) {
1233           /*
1234           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1235           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1236           //pic16_allocDirReg (IC_LEFT(ic));
1237           aop->size = getSize(sym->type);
1238           */
1239
1240           unsigned i;
1241
1242           aop = op->aop = sym->aop = newAsmop(AOP_REG);
1243           aop->size = getSize(sym->type);
1244           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1245             aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1246
1247           DEBUGpic16_emitcode(";","%d",__LINE__);
1248           return;
1249         }
1250 #endif
1251         /* else spill location  */
1252         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1253             /* force a new aop if sizes differ */
1254             sym->usl.spillLoc->aop = NULL;
1255         }
1256
1257 #if 0
1258         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1259                             __FUNCTION__,__LINE__,
1260                             sym->usl.spillLoc->rname,
1261                             sym->rname, sym->usl.spillLoc->offset);
1262 #endif
1263
1264         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1265         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1266         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1267           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1268                                                   getSize(sym->type), 
1269                                                   sym->usl.spillLoc->offset, op);
1270         } else {
1271           fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1272           DEBUGpic16_emitcode (";","%s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1273           assert (getSize(sym->type) <= 1);
1274           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1275         }
1276         aop->size = getSize(sym->type);
1277
1278         return;
1279     }
1280
1281     {
1282       sym_link *type = operandType(op);
1283 #if 0
1284       if(IS_PTR_CONST(type)) 
1285 #else
1286       if(IS_CODEPTR(type)) 
1287 #endif
1288         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1289     }
1290
1291     /* must be in a register */
1292     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1293     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1294     aop->size = sym->nRegs;
1295     for ( i = 0 ; i < sym->nRegs ;i++)
1296         aop->aopu.aop_reg[i] = sym->regs[i];
1297 }
1298
1299 /*-----------------------------------------------------------------*/
1300 /* pic16_freeAsmop - free up the asmop given to an operand               */
1301 /*----------------------------------------------------------------*/
1302 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1303 {   
1304     asmop *aop ;
1305
1306     if (!op)
1307         aop = aaop;
1308     else 
1309         aop = op->aop;
1310
1311     if (!aop)
1312         return ;
1313
1314     if (aop->freed)
1315         goto dealloc; 
1316
1317     aop->freed = 1;
1318
1319     /* depending on the asmop type only three cases need work AOP_RO
1320        , AOP_R1 && AOP_STK */
1321 #if 1
1322     switch (aop->type) {
1323         case AOP_FSR0 :
1324             if (_G.fsr0Pushed ) {
1325                 if (pop) {
1326                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1327                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1328 //                    pic16_emitcode ("pop","ar0");
1329                     _G.fsr0Pushed--;
1330                 }
1331             }
1332             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1333             break;
1334
1335         case AOP_FSR2 :
1336             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1337             break;
1338
1339         case AOP_R0 :
1340             if (_G.r0Pushed ) {
1341                 if (pop) {
1342                     pic16_emitcode ("pop","ar0");     
1343                     _G.r0Pushed--;
1344                 }
1345             }
1346             bitVectUnSetBit(ic->rUsed,R0_IDX);
1347             break;
1348
1349         case AOP_R1 :
1350             if (_G.r1Pushed ) {
1351                 if (pop) {
1352                     pic16_emitcode ("pop","ar1");
1353                     _G.r1Pushed--;
1354                 }
1355             }
1356             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1357             break;
1358
1359         case AOP_STA:
1360           {
1361             int i;
1362
1363               /* we must store the result on stack */
1364               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1365                 // operands on stack are accessible via "FSR2 + index" with index
1366                 // starting at 2 for arguments and growing from 0 downwards for
1367                 // local variables (index == 0 is not assigned so we add one here)
1368                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1369                 if (soffs <= 0) {
1370                   assert (soffs < 0);
1371                   soffs++;
1372                 } // if
1373                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1374                 for(i=0;i<aop->size;i++) {
1375                   /* initialise for stack access via frame pointer */
1376                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1377                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1378                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1379                 }
1380         
1381                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1382               }
1383
1384               if(!_G.resDirect) {
1385                 for(i=0;i<aop->size;i++) {
1386                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1387
1388                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx))
1389                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1390                 }
1391                   
1392               }
1393               _G.resDirect = 0;
1394           }
1395           break;
1396 #if 0
1397         case AOP_STK :
1398         {
1399             int sz = aop->size;    
1400             int stk = aop->aopu.aop_stk + aop->size;
1401             bitVectUnSetBit(ic->rUsed,R0_IDX);
1402             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1403
1404             getFreePtr(ic,&aop,FALSE);
1405             
1406             if (options.stack10bit)
1407             {
1408                 /* I'm not sure what to do here yet... */
1409                 /* #STUB */
1410                 fprintf(stderr, 
1411                         "*** Warning: probably generating bad code for "
1412                         "10 bit stack mode.\n");
1413             }
1414             
1415             if (stk) {
1416                 pic16_emitcode ("mov","a,_bp");
1417                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1418                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1419             } else {
1420                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1421             }
1422
1423             while (sz--) {
1424                 pic16_emitcode("pop","acc");
1425                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1426                 if (!sz) break;
1427                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1428             }
1429             op->aop = aop;
1430             pic16_freeAsmop(op,NULL,ic,TRUE);
1431             if (_G.r0Pushed) {
1432                 pic16_emitcode("pop","ar0");
1433                 _G.r0Pushed--;
1434             }
1435
1436             if (_G.r1Pushed) {
1437                 pic16_emitcode("pop","ar1");
1438                 _G.r1Pushed--;
1439             }       
1440         }
1441 #endif
1442
1443     }
1444 #endif
1445
1446 dealloc:
1447     /* all other cases just dealloc */
1448     if (op ) {
1449         op->aop = NULL;
1450         if (IS_SYMOP(op)) {
1451             OP_SYMBOL(op)->aop = NULL;    
1452             /* if the symbol has a spill */
1453             if (SPIL_LOC(op))
1454                 SPIL_LOC(op)->aop = NULL;
1455         }
1456     }
1457 }
1458
1459 /*-----------------------------------------------------------------*/
1460 /* pic16_aopGet - for fetching value of the aop                          */
1461 /*-----------------------------------------------------------------*/
1462 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1463 {
1464     char *s = buffer ;
1465     char *rs;
1466
1467     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1468
1469     /* offset is greater than size then zero */
1470     if (offset > (aop->size - 1) &&
1471         aop->type != AOP_LIT)
1472         return zero;
1473
1474     /* depending on type */
1475     switch (aop->type) {
1476
1477     case AOP_FSR0:
1478     case AOP_FSR2:
1479       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1480       rs = Safe_calloc(1, strlen(s)+1);
1481       strcpy(rs, s);
1482       return (rs);
1483       
1484 #if 0
1485       /* if we need to increment it */
1486       while (offset > aop->coff)
1487         {
1488           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1489           aop->coff++;
1490         }
1491
1492       while (offset < aop->coff)
1493         {
1494           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1495           aop->coff--;
1496         }
1497       aop->coff = offset;
1498       if (aop->paged)
1499         {
1500           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1501           return (dname ? "acc" : "a");
1502         }
1503       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1504       rs = Safe_calloc (1, strlen (s) + 1);
1505       strcpy (rs, s);
1506       return rs;
1507 #endif
1508
1509         
1510     case AOP_IMMD:
1511         if (bit16) 
1512             sprintf (s,"%s",aop->aopu.aop_immd);
1513         else
1514             if (offset) 
1515                 sprintf(s,"(%s >> %d)",
1516                         aop->aopu.aop_immd,
1517                         offset*8);
1518             else
1519                 sprintf(s,"%s",
1520                         aop->aopu.aop_immd);
1521         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1522         rs = Safe_calloc(1,strlen(s)+1);
1523         strcpy(rs,s);   
1524         return rs;
1525         
1526     case AOP_DIR:
1527       if (offset) {
1528         sprintf(s,"(%s + %d)",
1529                 aop->aopu.aop_dir,
1530                 offset);
1531         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1532       } else
1533             sprintf(s,"%s",aop->aopu.aop_dir);
1534         rs = Safe_calloc(1,strlen(s)+1);
1535         strcpy(rs,s);   
1536         return rs;
1537         
1538     case AOP_REG:
1539       //if (dname) 
1540       //    return aop->aopu.aop_reg[offset]->dname;
1541       //else
1542             return aop->aopu.aop_reg[offset]->name;
1543         
1544     case AOP_CRY:
1545       //pic16_emitcode(";","%d",__LINE__);
1546       return aop->aopu.aop_dir;
1547         
1548     case AOP_ACC:
1549         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1550 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1551 //        assert( 0 );
1552 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1553         rs = Safe_strdup("WREG");
1554         return (rs);
1555
1556     case AOP_LIT:
1557         sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1558         rs = Safe_calloc(1,strlen(s)+1);
1559         strcpy(rs,s);   
1560         return rs;
1561         
1562     case AOP_STR:
1563         aop->coff = offset ;
1564
1565 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1566 //          dname)
1567 //          return "acc";
1568         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1569           aop->type = AOP_ACC;
1570           return Safe_strdup("WREG");
1571         }
1572         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1573         
1574         return aop->aopu.aop_str[offset];
1575         
1576     case AOP_PCODE:
1577       {
1578         pCodeOp *pcop = aop->aopu.pcop;
1579         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1580         if(pcop->name) {
1581           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1582           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1583           if (offset) {
1584             sprintf(s,"(%s + %d)", pcop->name, offset);
1585           } else {
1586             sprintf(s,"%s", pcop->name);
1587           }
1588         } else
1589           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1590
1591       }
1592       rs = Safe_calloc(1,strlen(s)+1);
1593       strcpy(rs,s);   
1594       return rs;
1595
1596 #if 0
1597     case AOP_PAGED:
1598       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1599       if (offset) {
1600         sprintf(s,"(%s + %d)",
1601                 aop->aopu.aop_dir,
1602                 offset);
1603       } else
1604             sprintf(s,"%s",aop->aopu.aop_dir);
1605       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1606       rs = Safe_calloc(1,strlen(s)+1);
1607       strcpy(rs,s);   
1608       return rs;
1609 #endif
1610
1611     case AOP_STA:
1612         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1613         return (rs);
1614         
1615     case AOP_STK:
1616 //        pCodeOp *pcop = aop->aop
1617         break;
1618
1619     }
1620
1621     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1622     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1623            "aopget got unsupported aop->type");
1624     exit(0);
1625 }
1626
1627
1628
1629 /* lock has the following meaning: When allocating temporary registers
1630  * for stack variables storage, the value of the temporary register is
1631  * saved on stack. Its value is restored at the end. This procedure is
1632  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1633  * a possibility that before a call to pic16_aopOp, a temporary register
1634  * is allocated for a while and it is freed after some time, this will
1635  * mess the stack and values will not be restored properly. So use lock=1
1636  * to allocate temporary registers used internally by the programmer, and
1637  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1638  * to inform the compiler developer about a possible bug. This is an internal
1639  * feature for developing the compiler -- VR */
1640  
1641 int _TempReg_lock = 0;
1642 /*-----------------------------------------------------------------*/
1643 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1644 /*-----------------------------------------------------------------*/
1645 pCodeOp *pic16_popGetTempReg(int lock)
1646 {
1647   pCodeOp *pcop;
1648   symbol *cfunc;
1649
1650 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1651     if(_TempReg_lock) {
1652 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1653     }
1654     
1655     _TempReg_lock += lock;
1656     
1657     cfunc = currFunc;
1658     currFunc = NULL;
1659
1660     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1661     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1662       PCOR(pcop)->r->wasUsed=1;
1663       PCOR(pcop)->r->isFree=0;
1664
1665       /* push value on stack */
1666       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1667     }
1668
1669     currFunc = cfunc;
1670
1671   return pcop;
1672 }
1673
1674 /*-----------------------------------------------------------------*/
1675 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1676 /*                           is not part of f, but don't save if   */
1677 /*                           inside v                              */
1678 /*-----------------------------------------------------------------*/
1679 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1680 {
1681   pCodeOp *pcop=NULL;
1682   symbol *cfunc;
1683   int i;
1684
1685 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1686
1687     if(_TempReg_lock) {
1688 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1689     }
1690
1691     _TempReg_lock += lock;
1692
1693     cfunc = currFunc;
1694     currFunc = NULL;
1695
1696     i = bitVectFirstBit(f);
1697     while(i < 128) {
1698
1699       /* bypass registers that are used by function */
1700       if(!bitVectBitValue(f, i)) {
1701       
1702         /* bypass registers that are already allocated for stack access */
1703         if(!bitVectBitValue(v, i))  {
1704         
1705 //          debugf("getting register rIdx = %d\n", i);
1706           /* ok, get the operand */
1707           pcop = pic16_newpCodeOpReg( i );
1708     
1709           /* should never by NULL */
1710           assert( pcop != NULL );
1711
1712           
1713           /* sanity check */
1714           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1715             int found=0;
1716             
1717               PCOR(pcop)->r->wasUsed=1;
1718               PCOR(pcop)->r->isFree=0;
1719
1720
1721               {
1722                 regs *sr;
1723               
1724                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1725
1726                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1727                       /* already used in previous steps, break */
1728                       found=1;          
1729                       break;
1730                     }
1731                   }
1732               }
1733
1734               /* caller takes care of the following */
1735 //              bitVectSetBit(v, i);
1736
1737               if(!found) {
1738                 /* push value on stack */
1739                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1740                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1741               }
1742           
1743             break;
1744           }
1745         }
1746       }
1747       i++;
1748     }
1749
1750     currFunc = cfunc;
1751
1752   return pcop;
1753 }
1754
1755
1756 /*-----------------------------------------------------------------*/
1757 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1758 /*-----------------------------------------------------------------*/
1759 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1760 {
1761   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1762
1763   _TempReg_lock -= lock;
1764
1765   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1766     PCOR(pcop)->r->isFree = 1;
1767
1768     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1769   }
1770 }
1771 /*-----------------------------------------------------------------*/
1772 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1773 /*-----------------------------------------------------------------*/
1774 pCodeOp *pic16_popGetLabel(unsigned int key)
1775 {
1776
1777   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1778
1779   if(key>max_key)
1780     max_key = key;
1781
1782   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1783 }
1784
1785 /*-----------------------------------------------------------------*/
1786 /* pic16_popCopyReg - copy a pcode operator                              */
1787 /*-----------------------------------------------------------------*/
1788 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1789 {
1790   pCodeOpReg *pcor;
1791
1792   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1793   memcpy (pcor, pc, sizeof (pCodeOpReg));
1794   pcor->r->wasUsed = 1;
1795   
1796   //pcor->pcop.type = pc->pcop.type;
1797   if(pc->pcop.name) {
1798     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1799       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1800   } else
1801     pcor->pcop.name = NULL;
1802
1803   //pcor->r = pc->r;
1804   //pcor->rIdx = pc->rIdx;
1805   //pcor->r->wasUsed=1;
1806   //pcor->instance = pc->instance;
1807
1808 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1809
1810   return PCOP(pcor);
1811 }
1812
1813 /*-----------------------------------------------------------------*/
1814 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1815 /*-----------------------------------------------------------------*/
1816 pCodeOp *pic16_popGetLit(int lit)
1817 {
1818   return pic16_newpCodeOpLit(lit);
1819 }
1820
1821 /*-----------------------------------------------------------------*/
1822 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1823 /*-----------------------------------------------------------------*/
1824 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1825 {
1826   return pic16_newpCodeOpLit2(lit, arg2);
1827 }
1828
1829
1830 /*-----------------------------------------------------------------*/
1831 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1832 /*-----------------------------------------------------------------*/
1833 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1834 {
1835   return pic16_newpCodeOpImmd(name, offset,index, 0);
1836 }
1837
1838
1839 /*-----------------------------------------------------------------*/
1840 /* pic16_popGet - asm operator to pcode operator conversion              */
1841 /*-----------------------------------------------------------------*/
1842 pCodeOp *pic16_popGetWithString(char *str)
1843 {
1844   pCodeOp *pcop;
1845
1846
1847   if(!str) {
1848     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1849     exit (1);
1850   }
1851
1852   pcop = pic16_newpCodeOp(str,PO_STR);
1853
1854   return pcop;
1855 }
1856
1857 /*-----------------------------------------------------------------*/
1858 /* pic16_popRegFromString -                                        */
1859 /*-----------------------------------------------------------------*/
1860 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1861 {
1862
1863   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1864   pcop->type = PO_DIR;
1865
1866   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1867   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1868
1869   if(!str)
1870     str = "BAD_STRING";
1871
1872   pcop->name = Safe_calloc(1,strlen(str)+1);
1873   strcpy(pcop->name,str);
1874
1875   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1876
1877   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1878
1879   /* make sure that register doesn't exist,
1880    * and operand isn't NULL
1881    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1882   if((PCOR(pcop)->r == NULL) 
1883     && (op)
1884     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1885 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1886 //              __FUNCTION__, __LINE__, str, size, offset);
1887
1888     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1889     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1890
1891   }
1892   PCOR(pcop)->instance = offset;
1893
1894   return pcop;
1895 }
1896
1897 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1898 {
1899   pCodeOp *pcop;
1900
1901 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1902
1903         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1904         PCOR(pcop)->rIdx = rIdx;
1905         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1906
1907         PCOR(pcop)->r->isFree = 0;
1908         PCOR(pcop)->r->wasUsed = 1;
1909
1910         pcop->type = PCOR(pcop)->r->pc_type;
1911
1912   return pcop;
1913 }
1914
1915 /*---------------------------------------------------------------------------------*/
1916 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1917 /*                 VR 030601                                                       */
1918 /*---------------------------------------------------------------------------------*/
1919 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1920 {
1921   pCodeOpReg2 *pcop2;
1922   pCodeOp *temp;
1923   
1924         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1925
1926         /* comment the following check, so errors to throw up */
1927 //      if(!pcop2)return NULL;
1928
1929         temp = pic16_popGet(aop_dst, offset);
1930         pcop2->pcop2 = temp;
1931         
1932   return PCOP(pcop2);
1933 }
1934
1935
1936
1937 /*--------------------------------------------------------------------------------.-*/
1938 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1939 /*                  VR 030601 , adapted by Hans Dorn                                */
1940 /*--------------------------------------------------------------------------------.-*/
1941 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1942 {
1943   pCodeOpReg2 *pcop2;
1944  
1945         pcop2 = (pCodeOpReg2 *)src;
1946         pcop2->pcop2 = dst;
1947         
1948         return PCOP(pcop2);
1949 }
1950
1951
1952
1953 /*---------------------------------------------------------------------------------*/
1954 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1955 /*                     movff instruction                                           */
1956 /*---------------------------------------------------------------------------------*/
1957 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1958 {
1959   pCodeOpReg2 *pcop2;
1960
1961         if(!noalloc) {
1962                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1963                 pcop2->pcop2 = pic16_popCopyReg(dst);
1964         } else {
1965                 /* the pCodeOp may be already allocated */
1966                 pcop2 = (pCodeOpReg2 *)(src);
1967                 pcop2->pcop2 = (pCodeOp *)(dst);
1968         }
1969
1970   return PCOP(pcop2);
1971 }
1972
1973
1974 /*-----------------------------------------------------------------*/
1975 /* pic16_popGet - asm operator to pcode operator conversion              */
1976 /*-----------------------------------------------------------------*/
1977 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1978 {
1979   //char *s = buffer ;
1980   char *rs;
1981   pCodeOp *pcop;
1982
1983     FENTRY2;
1984     /* offset is greater than
1985     size then zero */
1986
1987 //    if (offset > (aop->size - 1) &&
1988 //        aop->type != AOP_LIT)
1989 //      return NULL;  //zero;
1990
1991     /* depending on type */
1992     switch (aop->type) {
1993         
1994     case AOP_R0:
1995     case AOP_R1:
1996     case AOP_DPTR:
1997     case AOP_DPTR2:
1998         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1999         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2000         assert( 0 );
2001         return NULL;
2002
2003
2004     case AOP_FSR0:
2005     case AOP_FSR2:
2006       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2007       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
2008       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2009       PCOR(pcop)->r->wasUsed = 1;
2010       PCOR(pcop)->r->isFree = 0;
2011       
2012       PCOR(pcop)->instance = offset;
2013       pcop->type = PCOR(pcop)->r->pc_type;
2014       return (pcop);
2015
2016     case AOP_IMMD:
2017       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2018       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2019
2020     case AOP_STA:
2021       /* pCodeOp is already allocated from aopForSym */
2022         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2023         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2024           
2025       return (pcop);
2026       
2027     case AOP_ACC:
2028       {
2029         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
2030
2031         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2032
2033         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2034         
2035         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2036         PCOR(pcop)->rIdx = rIdx;
2037         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2038         PCOR(pcop)->r->wasUsed=1;
2039         PCOR(pcop)->r->isFree=0;
2040
2041         PCOR(pcop)->instance = offset;
2042         pcop->type = PCOR(pcop)->r->pc_type;
2043 //      rs = aop->aopu.aop_reg[offset]->name;
2044 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2045         return pcop;
2046
2047
2048 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2049 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2050
2051 //      assert( 0 );
2052       }
2053         
2054     case AOP_DIR:
2055       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2056       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2057         
2058 #if 0
2059     case AOP_PAGED:
2060       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2061       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2062 #endif
2063
2064     case AOP_REG:
2065       {
2066         int rIdx;
2067         assert (aop && aop->aopu.aop_reg[offset] != NULL);
2068         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2069
2070         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2071         
2072         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2073 //      pcop->type = PO_GPR_REGISTER;
2074         PCOR(pcop)->rIdx = rIdx;
2075         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
2076         PCOR(pcop)->r->wasUsed=1;
2077         PCOR(pcop)->r->isFree=0;
2078
2079         PCOR(pcop)->instance = offset;
2080         pcop->type = PCOR(pcop)->r->pc_type;
2081         
2082         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2083         rs = aop->aopu.aop_reg[offset]->name;
2084         DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2085         return pcop;
2086       }
2087
2088     case AOP_CRY:
2089         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2090
2091       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2092       PCOR(pcop)->instance = offset;
2093       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2094       //if(PCOR(pcop)->r == NULL)
2095       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2096       return pcop;
2097         
2098     case AOP_LIT:
2099         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2100       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2101
2102     case AOP_STR:
2103       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2104       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2105
2106       /*
2107       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2108       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2109       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2110       pcop->type = PCOR(pcop)->r->pc_type;
2111       pcop->name = PCOR(pcop)->r->name;
2112
2113       return pcop;
2114       */
2115
2116     case AOP_PCODE:
2117       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2118                           __LINE__, 
2119                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2120       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2121       switch( aop->aopu.pcop->type ) {
2122         case PO_DIR: PCOR(pcop)->instance += offset; break;
2123         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2124         case PO_WREG:
2125             assert (offset==0);
2126             break;
2127         default:
2128           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2129           assert( 0 );  /* should never reach here */;
2130       }
2131       return pcop;
2132     }
2133
2134     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2135            "pic16_popGet got unsupported aop->type");
2136     exit(0);
2137 }
2138 /*-----------------------------------------------------------------*/
2139 /* pic16_aopPut - puts a string for a aop                                */
2140 /*-----------------------------------------------------------------*/
2141 void pic16_aopPut (asmop *aop, char *s, int offset)
2142 {
2143     char *d = buffer ;
2144     symbol *lbl ;
2145
2146     return;
2147
2148     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2149
2150     if (aop->size && offset > ( aop->size - 1)) {
2151         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2152                "pic16_aopPut got offset > aop->size");
2153         exit(0);
2154     }
2155
2156     /* will assign value to value */
2157     /* depending on where it is ofcourse */
2158     switch (aop->type) {
2159     case AOP_DIR:
2160       if (offset) {
2161         sprintf(d,"(%s + %d)",
2162                 aop->aopu.aop_dir,offset);
2163         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2164
2165       } else
2166             sprintf(d,"%s",aop->aopu.aop_dir);
2167         
2168         if (strcmp(d,s)) {
2169           DEBUGpic16_emitcode(";","%d",__LINE__);
2170           if(strcmp(s,"W"))
2171             pic16_emitcode("movf","%s,w",s);
2172           pic16_emitcode("movwf","%s",d);
2173
2174           if(strcmp(s,"W")) {
2175             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2176             if(offset >= aop->size) {
2177               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2178               break;
2179             } else
2180               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2181           }
2182
2183           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2184
2185
2186         }
2187         break;
2188         
2189     case AOP_REG:
2190       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2191         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2192           /*
2193             if (*s == '@'           ||
2194                 strcmp(s,"r0") == 0 ||
2195                 strcmp(s,"r1") == 0 ||
2196                 strcmp(s,"r2") == 0 ||
2197                 strcmp(s,"r3") == 0 ||
2198                 strcmp(s,"r4") == 0 ||
2199                 strcmp(s,"r5") == 0 ||
2200                 strcmp(s,"r6") == 0 || 
2201                 strcmp(s,"r7") == 0 )
2202                 pic16_emitcode("mov","%s,%s  ; %d",
2203                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2204             else
2205           */
2206
2207           if(strcmp(s,"W")==0 )
2208             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2209
2210           pic16_emitcode("movwf","%s",
2211                    aop->aopu.aop_reg[offset]->name);
2212
2213           if(strcmp(s,zero)==0) {
2214             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2215
2216           } else if(strcmp(s,"W")==0) {
2217             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2218             pcop->type = PO_GPR_REGISTER;
2219
2220             PCOR(pcop)->rIdx = -1;
2221             PCOR(pcop)->r = NULL;
2222
2223             DEBUGpic16_emitcode(";","%d",__LINE__);
2224             pcop->name = Safe_strdup(s);
2225             pic16_emitpcode(POC_MOVFW,pcop);
2226             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2227           } else if(strcmp(s,one)==0) {
2228             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2229             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2230           } else {
2231             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2232           }
2233         }
2234         break;
2235         
2236     case AOP_DPTR:
2237     case AOP_DPTR2:
2238     
2239     if (aop->type == AOP_DPTR2)
2240     {
2241         genSetDPTR(1);
2242     }
2243     
2244         if (aop->code) {
2245             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2246                    "pic16_aopPut writting to code space");
2247             exit(0);
2248         }
2249         
2250         while (offset > aop->coff) {
2251             aop->coff++;
2252             pic16_emitcode ("inc","dptr");
2253         }
2254         
2255         while (offset < aop->coff) {
2256             aop->coff-- ;
2257             pic16_emitcode("lcall","__decdptr");
2258         }
2259         
2260         aop->coff = offset;
2261         
2262         /* if not in accumulater */
2263         MOVA(s);        
2264         
2265         pic16_emitcode ("movx","@dptr,a");
2266         
2267     if (aop->type == AOP_DPTR2)
2268     {
2269         genSetDPTR(0);
2270     }
2271         break;
2272         
2273     case AOP_R0:
2274     case AOP_R1:
2275         while (offset > aop->coff) {
2276             aop->coff++;
2277             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2278         }
2279         while (offset < aop->coff) {
2280             aop->coff-- ;
2281             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2282         }
2283         aop->coff = offset;
2284         
2285         if (aop->paged) {
2286             MOVA(s);           
2287             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2288             
2289         } else
2290             if (*s == '@') {
2291                 MOVA(s);
2292                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2293             } else
2294                 if (strcmp(s,"r0") == 0 ||
2295                     strcmp(s,"r1") == 0 ||
2296                     strcmp(s,"r2") == 0 ||
2297                     strcmp(s,"r3") == 0 ||
2298                     strcmp(s,"r4") == 0 ||
2299                     strcmp(s,"r5") == 0 ||
2300                     strcmp(s,"r6") == 0 || 
2301                     strcmp(s,"r7") == 0 ) {
2302                     char buffer[10];
2303                     sprintf(buffer,"a%s",s);
2304                     pic16_emitcode("mov","@%s,%s",
2305                              aop->aopu.aop_ptr->name,buffer);
2306                 } else
2307                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2308         
2309         break;
2310         
2311     case AOP_STK:
2312         if (strcmp(s,"a") == 0)
2313             pic16_emitcode("push","acc");
2314         else
2315             pic16_emitcode("push","%s",s);
2316         
2317         break;
2318         
2319     case AOP_CRY:
2320         /* if bit variable */
2321         if (!aop->aopu.aop_dir) {
2322             pic16_emitcode("clr","a");
2323             pic16_emitcode("rlc","a");
2324         } else {
2325             if (s == zero) 
2326                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2327             else
2328                 if (s == one)
2329                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2330                 else
2331                     if (!strcmp(s,"c"))
2332                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2333                     else {
2334                         lbl = newiTempLabel(NULL);
2335                         
2336                         if (strcmp(s,"a")) {
2337                             MOVA(s);
2338                         }
2339                         pic16_emitcode("clr","c");
2340                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2341                         pic16_emitcode("cpl","c");
2342                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2343                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2344                     }
2345         }
2346         break;
2347         
2348     case AOP_STR:
2349         aop->coff = offset;
2350         if (strcmp(aop->aopu.aop_str[offset],s))
2351             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2352         break;
2353         
2354     case AOP_ACC:
2355         aop->coff = offset;
2356         if (!offset && (strcmp(s,"acc") == 0))
2357             break;
2358         
2359         if (strcmp(aop->aopu.aop_str[offset],s))
2360             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2361         break;
2362
2363     default :
2364         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2365 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2366 //             "pic16_aopPut got unsupported aop->type");
2367 //      exit(0);    
2368     }    
2369
2370 }
2371
2372 /*-----------------------------------------------------------------*/
2373 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2374 /*-----------------------------------------------------------------*/
2375 void pic16_mov2w (asmop *aop, int offset)
2376 {
2377   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2378
2379   if(is_LitAOp(aop))
2380     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2381   else
2382     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2383 }
2384
2385 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2386 {
2387   if(is_LitAOp(src)) {
2388     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2389     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2390   } else {
2391     if(pic16_sameRegsOfs(src, dst, offset))return;
2392     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2393                       pic16_popGet(dst, offset)));
2394   }
2395 }
2396
2397 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2398 {
2399   if(is_LitAOp(src)) {
2400     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2401     pic16_emitpcode(POC_MOVWF, dst);
2402   } else {
2403     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2404   }
2405 }
2406
2407 void pic16_testStackOverflow(void)
2408 {
2409 #define GSTACK_TEST_NAME        "_gstack_test"
2410
2411   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2412   
2413   {
2414     symbol *sym;
2415
2416       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2417       sprintf(sym->rname, "%s%s", port->fun_prefix, GSTACK_TEST_NAME);
2418 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2419       checkAddSym(&externs, sym);
2420   }
2421
2422 }
2423
2424 /* push pcop into stack */
2425 void pic16_pushpCodeOp(pCodeOp *pcop)
2426 {
2427 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2428   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));    //&pic16_pc_postdec1)));
2429   if(pic16_options.gstack)
2430     pic16_testStackOverflow();
2431     
2432 }
2433
2434 /* pop pcop from stack */
2435 void pic16_poppCodeOp(pCodeOp *pcop)
2436 {
2437   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2438   if(pic16_options.gstack)
2439     pic16_testStackOverflow();
2440 }
2441
2442
2443 /*-----------------------------------------------------------------*/
2444 /* pushw - pushes wreg to stack                                    */
2445 /*-----------------------------------------------------------------*/
2446 void pushw(void)
2447 {
2448   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2449   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2450   if(pic16_options.gstack)
2451     pic16_testStackOverflow();
2452 }
2453
2454                 
2455 /*-----------------------------------------------------------------*/
2456 /* pushaop - pushes aop to stack                                   */
2457 /*-----------------------------------------------------------------*/
2458 void pushaop(asmop *aop, int offset)
2459 {
2460   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2461
2462   if(is_LitAOp(aop)) {
2463     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2464     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2465   } else {
2466     pic16_emitpcode(POC_MOVFF,
2467       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2468   }
2469
2470   if(pic16_options.gstack)
2471     pic16_testStackOverflow();
2472 }
2473
2474 /*-----------------------------------------------------------------*/
2475 /* popaop - pops aop from stack                                    */
2476 /*-----------------------------------------------------------------*/
2477 void popaop(asmop *aop, int offset)
2478 {
2479   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2480   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2481   if(pic16_options.gstack)
2482     pic16_testStackOverflow();
2483 }
2484
2485 void popaopidx(asmop *aop, int offset, int index)
2486 {
2487   int ofs=1;
2488
2489     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2490
2491     if(STACK_MODEL_LARGE)ofs++;
2492
2493     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2494     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2495     if(pic16_options.gstack)
2496       pic16_testStackOverflow();
2497 }
2498
2499 #if !(USE_GENERIC_SIGNED_SHIFT)
2500 /*-----------------------------------------------------------------*/
2501 /* reAdjustPreg - points a register back to where it should        */
2502 /*-----------------------------------------------------------------*/
2503 static void reAdjustPreg (asmop *aop)
2504 {
2505     int size ;
2506
2507     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2508     aop->coff = 0;
2509     if ((size = aop->size) <= 1)
2510         return ;
2511     size-- ;
2512     switch (aop->type) {
2513         case AOP_R0 :
2514         case AOP_R1 :
2515             while (size--)
2516                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2517             break;          
2518         case AOP_DPTR :
2519         case AOP_DPTR2:
2520             if (aop->type == AOP_DPTR2)
2521             {
2522                 genSetDPTR(1);
2523             } 
2524             while (size--)
2525             {
2526                 pic16_emitcode("lcall","__decdptr");
2527             }
2528                 
2529             if (aop->type == AOP_DPTR2)
2530             {
2531                 genSetDPTR(0);
2532             }                
2533             break;  
2534
2535     }   
2536
2537 }
2538 #endif
2539
2540 #if 0
2541 /*-----------------------------------------------------------------*/
2542 /* opIsGptr: returns non-zero if the passed operand is             */   
2543 /* a generic pointer type.                                         */
2544 /*-----------------------------------------------------------------*/ 
2545 static int opIsGptr(operand *op)
2546 {
2547     sym_link *type = operandType(op);
2548     
2549     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2550     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2551     {
2552         return 1;
2553     }
2554     return 0;        
2555 }
2556 #endif
2557
2558 /*-----------------------------------------------------------------*/
2559 /* pic16_getDataSize - get the operand data size                         */
2560 /*-----------------------------------------------------------------*/
2561 int pic16_getDataSize(operand *op)
2562 {
2563     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2564
2565
2566     return AOP_SIZE(op);
2567
2568     // tsd- in the pic port, the genptr size is 1, so this code here
2569     // fails. ( in the 8051 port, the size was 4).
2570 #if 0
2571     int size;
2572     size = AOP_SIZE(op);
2573     if (size == GPTRSIZE)
2574     {
2575         sym_link *type = operandType(op);
2576         if (IS_GENPTR(type))
2577         {
2578             /* generic pointer; arithmetic operations
2579              * should ignore the high byte (pointer type).
2580              */
2581             size--;
2582     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2583         }
2584     }
2585     return size;
2586 #endif
2587 }
2588
2589 /*-----------------------------------------------------------------*/
2590 /* pic16_outAcc - output Acc                                             */
2591 /*-----------------------------------------------------------------*/
2592 void pic16_outAcc(operand *result)
2593 {
2594   int size,offset;
2595   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2596   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2597
2598
2599   size = pic16_getDataSize(result);
2600   if(size){
2601     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2602     size--;
2603     offset = 1;
2604     /* unsigned or positive */
2605     while(size--)
2606       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2607   }
2608
2609 }
2610
2611 /*-----------------------------------------------------------------*/
2612 /* pic16_outBitC - output a bit C                                  */
2613 /*                 Move to result the value of Carry flag -- VR    */
2614 /*-----------------------------------------------------------------*/
2615 void pic16_outBitC(operand *result)
2616 {
2617   int i;
2618
2619     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2620
2621     /* if the result is bit */
2622     if (AOP_TYPE(result) == AOP_CRY) {
2623         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2624         pic16_aopPut(AOP(result),"c",0);
2625     } else {
2626
2627         i = AOP_SIZE(result);
2628         while(i--) {
2629                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2630         }
2631         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2632     }
2633 }
2634
2635 /*-----------------------------------------------------------------*/
2636 /* pic16_outBitOp - output a bit from Op                           */
2637 /*                 Move to result the value of set/clr op -- VR    */
2638 /*-----------------------------------------------------------------*/
2639 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2640 {
2641   int i;
2642
2643     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2644
2645     /* if the result is bit */
2646     if (AOP_TYPE(result) == AOP_CRY) {
2647         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2648         pic16_aopPut(AOP(result),"c",0);
2649     } else {
2650
2651         i = AOP_SIZE(result);
2652         while(i--) {
2653                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2654         }
2655         pic16_emitpcode(POC_RRCF, pcop);          
2656         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2657     }
2658 }
2659
2660 /*-----------------------------------------------------------------*/
2661 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2662 /*-----------------------------------------------------------------*/
2663 void pic16_toBoolean(operand *oper)
2664 {
2665     int size = AOP_SIZE(oper) - 1;
2666     int offset = 1;
2667
2668     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2669
2670     if ( AOP_TYPE(oper) != AOP_ACC) {
2671       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2672     }
2673     while (size--) {
2674       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2675     }
2676 }
2677
2678
2679 #if !defined(GEN_Not)
2680 /*-----------------------------------------------------------------*/
2681 /* genNot - generate code for ! operation                          */
2682 /*-----------------------------------------------------------------*/
2683 static void pic16_genNot (iCode *ic)
2684 {
2685   symbol *tlbl;
2686   int size;
2687
2688   FENTRY;
2689   /* assign asmOps to operand & result */
2690   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2691   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2692
2693   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2694   /* if in bit space then a special case */
2695   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2696     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2697       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2698       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2699     } else {
2700       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2701       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2702       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2703     }
2704     goto release;
2705   }
2706
2707   size = AOP_SIZE(IC_LEFT(ic));
2708   if(size == 1) {
2709     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2710     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2711     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2712     goto release;
2713   }
2714   pic16_toBoolean(IC_LEFT(ic));
2715
2716   tlbl = newiTempLabel(NULL);
2717   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2718   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2719   pic16_outBitC(IC_RESULT(ic));
2720
2721  release:    
2722   /* release the aops */
2723   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2724   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2725 }
2726 #endif
2727
2728
2729 #if !defined(GEN_Cpl)
2730 /*-----------------------------------------------------------------*/
2731 /* genCpl - generate code for complement                           */
2732 /*-----------------------------------------------------------------*/
2733 static void pic16_genCpl (iCode *ic)
2734 {
2735   int offset = 0;
2736   int size ;
2737
2738     FENTRY;
2739     /* assign asmOps to operand & result */
2740     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2741     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2742
2743     /* if both are in bit space then 
2744     a special case */
2745     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2746         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2747
2748         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2749         pic16_emitcode("cpl","c"); 
2750         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2751         goto release; 
2752     } 
2753
2754     size = AOP_SIZE(IC_RESULT(ic));
2755     while (size--) {
2756 /*
2757         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2758         MOVA(l);       
2759         pic16_emitcode("cpl","a");
2760         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2761 */
2762         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2763               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2764         } else {
2765                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2766                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2767         }
2768         offset++;
2769
2770     }
2771
2772
2773 release:
2774     /* release the aops */
2775     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2776     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2777 }
2778 #endif
2779
2780 /*-----------------------------------------------------------------*/
2781 /* genUminusFloat - unary minus for floating points                */
2782 /*-----------------------------------------------------------------*/
2783 static void genUminusFloat(operand *op,operand *result)
2784 {
2785   int size ,offset =0 ;
2786   
2787     FENTRY;
2788     /* for this we just need to flip the 
2789     first it then copy the rest in place */
2790     size = AOP_SIZE(op);
2791
2792     while(size--) {
2793       pic16_mov2f(AOP(result), AOP(op), offset);
2794       offset++;
2795     }
2796     
2797     /* toggle the MSB's highest bit */
2798     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2799 }
2800
2801 /*-----------------------------------------------------------------*/
2802 /* genUminus - unary minus code generation                         */
2803 /*-----------------------------------------------------------------*/
2804 static void genUminus (iCode *ic)
2805 {
2806   int size, i;
2807   sym_link *optype, *rtype;
2808   symbol *label;
2809   int needLabel=0;
2810
2811     FENTRY;     
2812     
2813     /* assign asmops */
2814     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2815     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2816
2817     /* if both in bit space then special case */
2818     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2819       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2820         
2821         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2822         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2823         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2824         goto release; 
2825     } 
2826
2827     optype = operandType(IC_LEFT(ic));
2828     rtype = operandType(IC_RESULT(ic));
2829
2830     /* if float then do float stuff */
2831     if (IS_FLOAT(optype)) {
2832       genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2833       goto release;
2834     }
2835
2836     /* otherwise subtract from zero by taking the 2's complement */
2837     size = AOP_SIZE(IC_LEFT(ic));
2838     label = newiTempLabel ( NULL );
2839     
2840     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2841       for (i=size-1; i > 0; i--) {
2842         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2843       } // for
2844       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2845       for (i=1; i < size; i++) {
2846         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2847         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2848       } // for
2849     } else {
2850       for (i=size-1; i >= 0; i--) {
2851         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2852         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2853       } // for
2854       if (size > 1) {
2855         for (i=0; i < size-2; i++) {
2856           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2857           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2858         } // for
2859         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2860       } // if
2861       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2862     }
2863     if (needLabel)
2864       pic16_emitpLabel (label->key);
2865
2866 release:
2867     /* release the aops */
2868     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2869     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2870 }
2871
2872 #if 0
2873 /*-----------------------------------------------------------------*/
2874 /* saveRegisters - will look for a call and save the registers     */
2875 /*-----------------------------------------------------------------*/
2876 static void saveRegisters(iCode *lic) 
2877 {
2878     int i;
2879     iCode *ic;
2880     bitVect *rsave;
2881     sym_link *dtype;
2882
2883     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2884     /* look for call */
2885     for (ic = lic ; ic ; ic = ic->next) 
2886         if (ic->op == CALL || ic->op == PCALL)
2887             break;
2888
2889     if (!ic) {
2890         fprintf(stderr,"found parameter push with no function call\n");
2891         return ;
2892     }
2893
2894     /* if the registers have been saved already then
2895     do nothing */
2896     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2897         return ;
2898
2899     /* find the registers in use at this time 
2900     and push them away to safety */
2901     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2902                           ic->rUsed);
2903
2904     ic->regsSaved = 1;
2905     if (options.useXstack) {
2906         if (bitVectBitValue(rsave,R0_IDX))
2907             pic16_emitcode("mov","b,r0");
2908         pic16_emitcode("mov","r0,%s",spname);
2909         for (i = 0 ; i < pic16_nRegs ; i++) {
2910             if (bitVectBitValue(rsave,i)) {
2911                 if (i == R0_IDX)
2912                     pic16_emitcode("mov","a,b");
2913                 else
2914                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2915                 pic16_emitcode("movx","@r0,a");
2916                 pic16_emitcode("inc","r0");
2917             }
2918         }
2919         pic16_emitcode("mov","%s,r0",spname);
2920         if (bitVectBitValue(rsave,R0_IDX))
2921             pic16_emitcode("mov","r0,b");           
2922     }// else
2923     //for (i = 0 ; i < pic16_nRegs ; i++) {
2924     //    if (bitVectBitValue(rsave,i))
2925     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2926     //}
2927
2928     dtype = operandType(IC_LEFT(ic));
2929     if (currFunc && dtype && 
2930         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2931         IFFUNC_ISISR(currFunc->type) &&
2932         !ic->bankSaved) 
2933
2934         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2935
2936 }
2937 /*-----------------------------------------------------------------*/
2938 /* unsaveRegisters - pop the pushed registers                      */
2939 /*-----------------------------------------------------------------*/
2940 static void unsaveRegisters (iCode *ic)
2941 {
2942     int i;
2943     bitVect *rsave;
2944
2945     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2946     /* find the registers in use at this time 
2947     and push them away to safety */
2948     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2949                           ic->rUsed);
2950     
2951     if (options.useXstack) {
2952         pic16_emitcode("mov","r0,%s",spname);   
2953         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2954             if (bitVectBitValue(rsave,i)) {
2955                 pic16_emitcode("dec","r0");
2956                 pic16_emitcode("movx","a,@r0");
2957                 if (i == R0_IDX)
2958                     pic16_emitcode("mov","b,a");
2959                 else
2960                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2961             }       
2962
2963         }
2964         pic16_emitcode("mov","%s,r0",spname);
2965         if (bitVectBitValue(rsave,R0_IDX))
2966             pic16_emitcode("mov","r0,b");
2967     } //else
2968     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2969     //    if (bitVectBitValue(rsave,i))
2970     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2971     //}
2972
2973 }  
2974 #endif
2975
2976 #if 0  // patch 14
2977 /*-----------------------------------------------------------------*/
2978 /* pushSide -                                                      */
2979 /*-----------------------------------------------------------------*/
2980 static void pushSide(operand * oper, int size)
2981 {
2982         int offset = 0;
2983     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2984         while (size--) {
2985                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2986                 if (AOP_TYPE(oper) != AOP_REG &&
2987                     AOP_TYPE(oper) != AOP_DIR &&
2988                     strcmp(l,"a") ) {
2989                         pic16_emitcode("mov","a,%s",l);
2990                         pic16_emitcode("push","acc");
2991                 } else
2992                         pic16_emitcode("push","%s",l);
2993         }
2994 }
2995 #endif // patch 14
2996
2997 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2998 {
2999   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3000     pic16_emitpcode(POC_MOVFW, src);
3001     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
3002   } else {
3003     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3004         src, pic16_popGet(AOP(op), offset)));
3005   }
3006 }
3007
3008
3009 /*-----------------------------------------------------------------*/
3010 /* assignResultValue - assign results to oper, rescall==1 is       */
3011 /*                     called from genCall() or genPcall()         */
3012 /*-----------------------------------------------------------------*/
3013 static void assignResultValue(operand * oper, int rescall)
3014 {
3015   int size = AOP_SIZE(oper);
3016   int offset=0;
3017   
3018     FENTRY2;
3019 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3020     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3021
3022     if(rescall) {
3023       /* assign result from a call/pcall function() */
3024                 
3025       /* function results are stored in a special order,
3026        * see top of file with Function return policy, or manual */
3027
3028       if(size <= 4) {
3029         /* 8-bits, result in WREG */
3030         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3031                         
3032         if(size>1) {
3033           /* 16-bits, result in PRODL:WREG */
3034           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3035         }
3036                         
3037         if(size>2) {
3038           /* 24-bits, result in PRODH:PRODL:WREG */
3039           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3040         }
3041                         
3042         if(size>3) {
3043           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3044           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3045         }
3046       
3047       } else {
3048         /* >32-bits, result on stack, and FSR0 points to beginning.
3049          * Fix stack when done */
3050         /* FIXME FIXME */
3051 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3052         while (size--) {
3053 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3054 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3055                 
3056           popaopidx(AOP(oper), size, GpsuedoStkPtr);
3057           GpsuedoStkPtr++;
3058         }
3059                         
3060         /* fix stack */
3061         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3062         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3063         if(STACK_MODEL_LARGE) {
3064           emitSKPNC;
3065           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3066         }
3067       }                 
3068     } else {
3069       int areg = 0;             /* matching argument register */
3070       
3071 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3072       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3073
3074
3075       /* its called from genReceive (probably) -- VR */
3076       /* I hope this code will not be called from somewhere else in the future! 
3077        * We manually set the pseudo stack pointer in genReceive. - dw
3078        */
3079       if(!GpsuedoStkPtr && _G.useWreg) {
3080 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3081
3082         /* The last byte in the assignment is in W */
3083         if(areg <= GpsuedoStkPtr) {
3084           size--;
3085           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3086           offset++;
3087 //          debugf("receive from WREG\n", 0);
3088         }
3089         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3090       }
3091 //      GpsuedoStkPtr++;
3092       _G.stack_lat = AOP_SIZE(oper)-1;
3093
3094       while (size) {
3095         size--;
3096         GpsuedoStkPtr++;
3097         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3098 //        debugf("receive from STACK\n", 0);
3099         offset++;
3100       }
3101     }
3102 }
3103
3104
3105 /*-----------------------------------------------------------------*/
3106 /* genIpush - generate code for pushing this gets a little complex */
3107 /*-----------------------------------------------------------------*/
3108 static void genIpush (iCode *ic)
3109 {
3110 //  int size, offset=0;
3111
3112   FENTRY;
3113   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3114
3115   if(ic->parmPush) {
3116     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3117
3118     /* send to stack as normal */
3119     addSet(&_G.sendSet,ic);
3120 //    addSetHead(&_G.sendSet,ic);
3121     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3122   }
3123
3124         
3125 #if 0
3126     int size, offset = 0 ;
3127     char *l;
3128
3129
3130     /* if this is not a parm push : ie. it is spill push 
3131     and spill push is always done on the local stack */
3132     if (!ic->parmPush) {
3133
3134         /* and the item is spilt then do nothing */
3135         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3136             return ;
3137
3138         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3139         size = AOP_SIZE(IC_LEFT(ic));
3140         /* push it on the stack */
3141         while(size--) {
3142             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3143             if (*l == '#') {
3144                 MOVA(l);
3145                 l = "acc";
3146             }
3147             pic16_emitcode("push","%s",l);
3148         }
3149         return ;        
3150     }
3151
3152     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3153 #endif
3154 }
3155
3156 /*-----------------------------------------------------------------*/
3157 /* genIpop - recover the registers: can happen only for spilling   */
3158 /*-----------------------------------------------------------------*/
3159 static void genIpop (iCode *ic)
3160 {
3161   FENTRY;
3162   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3163 #if 0
3164     int size,offset ;
3165
3166
3167     /* if the temp was not pushed then */
3168     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3169         return ;
3170
3171     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3172     size = AOP_SIZE(IC_LEFT(ic));
3173     offset = (size-1);
3174     while (size--) 
3175         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3176                                    FALSE,TRUE));
3177
3178     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3179 #endif
3180 }
3181
3182 #if 0
3183 /*-----------------------------------------------------------------*/
3184 /* unsaverbank - restores the resgister bank from stack            */
3185 /*-----------------------------------------------------------------*/
3186 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3187 {
3188   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3189 #if 0
3190     int i;
3191     asmop *aop ;
3192     regs *r = NULL;
3193
3194     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3195     if (popPsw) {
3196         if (options.useXstack) {
3197             aop = newAsmop(0);
3198             r = getFreePtr(ic,&aop,FALSE);
3199             
3200             
3201             pic16_emitcode("mov","%s,_spx",r->name);
3202             pic16_emitcode("movx","a,@%s",r->name);
3203             pic16_emitcode("mov","psw,a");
3204             pic16_emitcode("dec","%s",r->name);
3205             
3206         }else
3207             pic16_emitcode ("pop","psw");
3208     }
3209
3210     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3211         if (options.useXstack) {       
3212             pic16_emitcode("movx","a,@%s",r->name);
3213             //pic16_emitcode("mov","(%s+%d),a",
3214             //       regspic16[i].base,8*bank+regspic16[i].offset);
3215             pic16_emitcode("dec","%s",r->name);
3216
3217         } else 
3218           pic16_emitcode("pop",""); //"(%s+%d)",
3219         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3220     }
3221
3222     if (options.useXstack) {
3223
3224         pic16_emitcode("mov","_spx,%s",r->name);
3225         pic16_freeAsmop(NULL,aop,ic,TRUE);
3226
3227     }
3228 #endif 
3229 }
3230
3231 /*-----------------------------------------------------------------*/
3232 /* saverbank - saves an entire register bank on the stack          */
3233 /*-----------------------------------------------------------------*/
3234 static void saverbank (int bank, iCode *ic, bool pushPsw)
3235 {
3236   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3237 #if 0
3238     int i;
3239     asmop *aop ;
3240     regs *r = NULL;
3241
3242     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3243     if (options.useXstack) {
3244
3245         aop = newAsmop(0);
3246         r = getFreePtr(ic,&aop,FALSE);  
3247         pic16_emitcode("mov","%s,_spx",r->name);
3248
3249     }
3250
3251     for (i = 0 ; i < pic16_nRegs ;i++) {
3252         if (options.useXstack) {
3253             pic16_emitcode("inc","%s",r->name);
3254             //pic16_emitcode("mov","a,(%s+%d)",
3255             //         regspic16[i].base,8*bank+regspic16[i].offset);
3256             pic16_emitcode("movx","@%s,a",r->name);           
3257         } else 
3258           pic16_emitcode("push","");// "(%s+%d)",
3259                      //regspic16[i].base,8*bank+regspic16[i].offset);
3260     }
3261     
3262     if (pushPsw) {
3263         if (options.useXstack) {
3264             pic16_emitcode("mov","a,psw");
3265             pic16_emitcode("movx","@%s,a",r->name);     
3266             pic16_emitcode("inc","%s",r->name);
3267             pic16_emitcode("mov","_spx,%s",r->name);       
3268             pic16_freeAsmop (NULL,aop,ic,TRUE);
3269             
3270         } else
3271             pic16_emitcode("push","psw");
3272         
3273         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3274     }
3275     ic->bankSaved = 1;
3276 #endif
3277 }
3278 #endif  /* 0 */
3279
3280
3281 static int wparamCmp(void *p1, void *p2)
3282 {
3283   return (!strcmp((char *)p1, (char *)p2));
3284 }
3285
3286 int inWparamList(char *s)
3287 {
3288   return isinSetWith(wparamList, s, wparamCmp);
3289
3290
3291
3292 /*-----------------------------------------------------------------*/
3293 /* genCall - generates a call statement                            */
3294 /*-----------------------------------------------------------------*/
3295 static void genCall (iCode *ic)
3296 {
3297   sym_link *ftype;   
3298   int stackParms=0;
3299   int use_wreg=0;
3300   int inwparam=0;
3301   char *fname;
3302   
3303     FENTRY;
3304
3305     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3306     /* if caller saves & we have not saved then */
3307 //    if (!ic->regsSaved)
3308 //      saveRegisters(ic);
3309
3310         /* initialise stackParms for IPUSH pushes */
3311 //      stackParms = psuedoStkPtr;
3312 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3313     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3314     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3315
3316 #if 0
3317     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3318 #endif
3319
3320     /* if send set is not empty the assign */
3321     if (_G.sendSet) {
3322       iCode *sic;
3323       int psuedoStkPtr=-1; 
3324       int firstTimeThruLoop = 1;
3325
3326
3327         /* reverse sendSet if function is not reentrant */
3328         if(!IFFUNC_ISREENT(ftype))
3329           _G.sendSet = reverseSet(_G.sendSet);
3330
3331         /* First figure how many parameters are getting passed */
3332         stackParms = 0;
3333         use_wreg = 0;
3334         
3335         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3336           int size;
3337 //          int offset = 0;
3338
3339             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3340             size = AOP_SIZE(IC_LEFT(sic));
3341
3342             stackParms += size;
3343
3344             /* pass the last byte through WREG */
3345             if(inwparam) {
3346
3347               while (size--) {
3348                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3349                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3350                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3351
3352                 if(!firstTimeThruLoop) {
3353                   /* If this is not the first time we've been through the loop
3354                    * then we need to save the parameter in a temporary
3355                    * register. The last byte of the last parameter is
3356                    * passed in W. */
3357
3358                   pushw();
3359 //                  --psuedoStkPtr;             // sanity check
3360                   use_wreg = 1;
3361                 }
3362                 
3363                 firstTimeThruLoop=0;
3364
3365                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3366
3367 //                offset++;
3368               }
3369             } else {
3370               /* all arguments are passed via stack */
3371               use_wreg = 0;
3372
3373               while (size--) {
3374                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3375                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3376                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3377
3378 //                pushaop(AOP(IC_LEFT(sic)), size);
3379                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3380
3381                 if(!_G.resDirect)
3382                   pushw();
3383               }
3384             }
3385
3386             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3387           }
3388
3389           if(inwparam) {
3390             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3391               pushw();  /* save last parameter to stack if functions has varargs */
3392               use_wreg = 0;
3393             } else
3394               use_wreg = 1;
3395           } else use_wreg = 0;
3396
3397           _G.stackRegSet = _G.sendSet;
3398           _G.sendSet = NULL;
3399     }
3400
3401     /* make the call */
3402     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3403
3404     GpsuedoStkPtr=0;
3405     
3406     /* if we need to assign a result value */
3407     if ((IS_ITEMP(IC_RESULT(ic))
3408           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3409               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3410         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3411
3412       _G.accInUse++;
3413       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3414       _G.accInUse--;
3415
3416       assignResultValue(IC_RESULT(ic), 1);
3417
3418       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3419                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3420                 
3421       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3422     }
3423
3424     if(!stackParms && ic->parmBytes) {
3425       stackParms = ic->parmBytes;
3426     }
3427       
3428     stackParms -= use_wreg;
3429     
3430     if(stackParms>0) {
3431       if(stackParms == 1) {
3432         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3433       } else {
3434         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3435         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3436       }
3437       if(STACK_MODEL_LARGE) {
3438         emitSKPNC;
3439         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3440       }
3441     }
3442
3443 #if 0
3444     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3445 #endif
3446
3447     /* adjust the stack for parameters if required */
3448 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3449
3450 #if 0
3451       /* if register bank was saved then pop them */
3452       if (ic->bankSaved)
3453         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3454
3455       /* if we hade saved some registers then unsave them */
3456       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3457         unsaveRegisters (ic);
3458 #endif
3459 }
3460
3461
3462
3463 /*-----------------------------------------------------------------*/
3464 /* genPcall - generates a call by pointer statement                */
3465 /*            new version, created from genCall - HJD              */
3466 /*-----------------------------------------------------------------*/
3467 static void genPcall (iCode *ic)
3468 {
3469   sym_link *ftype, *fntype;
3470   int stackParms=0;
3471   symbol *retlbl = newiTempLabel(NULL);
3472   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3473   
3474     FENTRY;
3475
3476     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3477     fntype = operandType( IC_LEFT(ic) )->next;
3478
3479     /* if send set is not empty the assign */
3480     if (_G.sendSet) {
3481       iCode *sic;
3482       int psuedoStkPtr=-1; 
3483
3484       /* reverse sendSet if function is not reentrant */
3485       if(!IFFUNC_ISREENT(fntype))
3486         _G.sendSet = reverseSet(_G.sendSet);
3487
3488       stackParms = 0;
3489       
3490       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3491         int size;
3492
3493           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3494           size = AOP_SIZE(IC_LEFT(sic));
3495           stackParms += size;
3496
3497           /* all parameters are passed via stack, since WREG is clobbered
3498            * by the calling sequence */
3499           while (size--) {
3500             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3501             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3502             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3503
3504             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3505             pushw();
3506           }
3507
3508           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3509       }
3510
3511       _G.stackRegSet = _G.sendSet;
3512       _G.sendSet = NULL;
3513     }
3514
3515     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3516
3517     // push return address
3518     // push $ on return stack, then replace with retlbl
3519
3520     /* Thanks to Thorsten Klose for pointing out that the following
3521      * snippet should be interrupt safe */
3522     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3523     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3524
3525     pic16_emitpcodeNULLop(POC_PUSH);
3526
3527     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3528     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3529     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3530     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3531     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3532     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3533
3534
3535     /* restore interrupt control register */
3536     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3537     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3538
3539     /* make the call by writing the pointer into pc */
3540     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3541     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3542
3543     // note: MOVFF to PCL not allowed
3544     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3545     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3546
3547
3548     /* return address is here: (X) */
3549     pic16_emitpLabelFORCE(retlbl->key);
3550
3551     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3552
3553     GpsuedoStkPtr=0;
3554     /* if we need assign a result value */
3555     if ((IS_ITEMP(IC_RESULT(ic))
3556           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3557               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3558         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3559
3560       _G.accInUse++;
3561       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3562       _G.accInUse--;
3563
3564       assignResultValue(IC_RESULT(ic), 1);
3565
3566       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3567               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3568                 
3569       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3570     }
3571
3572 //    stackParms -= use_wreg;
3573     
3574     if(stackParms>0) {
3575       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3576       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3577       if(STACK_MODEL_LARGE) {
3578         emitSKPNC;
3579         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3580       }
3581     }
3582 }
3583
3584 /*-----------------------------------------------------------------*/
3585 /* resultRemat - result  is rematerializable                       */
3586 /*-----------------------------------------------------------------*/
3587 static int resultRemat (iCode *ic)
3588 {
3589   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3590   if (SKIP_IC(ic) || ic->op == IFX)
3591     return 0;
3592
3593   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3594     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3595     if (sym->remat && !POINTER_SET(ic)) 
3596       return 1;
3597   }
3598
3599   return 0;
3600 }
3601
3602 #if defined(__BORLANDC__) || defined(_MSC_VER)
3603 #define STRCASECMP stricmp
3604 #else
3605 #define STRCASECMP strcasecmp
3606 #endif
3607
3608 #if 0
3609 /*-----------------------------------------------------------------*/
3610 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3611 /*-----------------------------------------------------------------*/
3612 static bool inExcludeList(char *s)
3613 {
3614   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3615     int i =0;
3616     
3617     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3618     if (options.excludeRegs[i] &&
3619     STRCASECMP(options.excludeRegs[i],"none") == 0)
3620         return FALSE ;
3621
3622     for ( i = 0 ; options.excludeRegs[i]; i++) {
3623         if (options.excludeRegs[i] &&
3624         STRCASECMP(s,options.excludeRegs[i]) == 0)
3625             return TRUE;
3626     }
3627     return FALSE ;
3628 }
3629 #endif
3630
3631 /*-----------------------------------------------------------------*/
3632 /* genFunction - generated code for function entry                 */
3633 /*-----------------------------------------------------------------*/
3634 static void genFunction (iCode *ic)
3635 {
3636   symbol *sym;
3637   sym_link *ftype;
3638   
3639     FENTRY;
3640     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3641
3642     pic16_labelOffset += (max_key+4);
3643     max_key=0;
3644     GpsuedoStkPtr=0;
3645     _G.nRegsSaved = 0;
3646         
3647     ftype = operandType(IC_LEFT(ic));
3648     sym = OP_SYMBOL(IC_LEFT(ic));
3649
3650     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3651       /* create an absolute section at the interrupt vector:
3652        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3653       symbol *asym;
3654       char asymname[128];
3655       pBlock *apb;
3656
3657 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3658
3659         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3660           sprintf(asymname, "ivec_%s", sym->name);
3661         else
3662           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3663   
3664         /* when an interrupt is declared as naked, do not emit the special
3665          * wrapper segment at vector address. The user should take care for
3666          * this instead. -- VR */
3667
3668         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3669           asym = newSymbol(asymname, 0);
3670           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3671           pic16_addpBlock( apb );
3672
3673           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3674           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3675           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3676           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3677           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
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_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         pic16_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                 pic16_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         pic16_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                 pic16_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       pic16_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     pic16_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                 pic16_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         pic16_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