2139f35871d6065614cdcc51483e02787250b9ab
[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   Bug Fixes  -  Raphael Neider rneider@web.de (2004,2005)
11   
12   This program is free software; you can redistribute it and/or modify it
13   under the terms of the GNU General Public License as published by the
14   Free Software Foundation; either version 2, or (at your option) any
15   later version.
16   
17   This program is distributed in the hope that it will be useful,
18   but WITHOUT ANY WARRANTY; without even the implied warranty of
19   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20   GNU General Public License for more details.
21   
22   You should have received a copy of the GNU General Public License
23   along with this program; if not, write to the Free Software
24   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25   
26   In other words, you are welcome to use, share and improve this program.
27   You are forbidden to forbid anyone else to use, share and improve
28   what you give them.   Help stamp out software-hoarding!
29   
30   Notes:
31   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
32                 Made everything static
33 -------------------------------------------------------------------------*/
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <ctype.h>
39 #include "SDCCglobl.h"
40 #include "newalloc.h"
41
42 #include "common.h"
43 #include "SDCCpeeph.h"
44 #include "ralloc.h"
45 #include "pcode.h"
46 #include "gen.h"
47 #include "genutils.h"
48 #include "device.h"
49 #include "main.h"
50
51 /* Set the following to 1 to enable the slower/bigger
52  * but more robust generic shifting routine (which also
53  * operates correctly with negative shift values). */
54 #define USE_GENERIC_SIGNED_SHIFT 1
55
56 /* Set the following to 1 to enable the new
57  * stripped down genCmp version.
58  * This version should be easier to understand,
59  * more reliable and (sigh) slighly slower. */
60 #define USE_SIMPLE_GENCMP 1
61
62 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
63 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
64 void pic16_genMult8X8_8 (operand *, operand *,operand *);
65 void pic16_genMult16X16_16(operand *, operand *, operand *);
66 void pic16_genMult32X32_32(operand *, operand *, operand *);
67 pCode *pic16_AssembleLine(char *line, int peeps);
68 extern void pic16_printpBlock(FILE *of, pBlock *pb);
69 static asmop *newAsmop (short type);
70 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
71 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
72 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
73 static pCodeOp *pic16_popRegFromIdx(int rIdx);
74
75 //static int aopIdx (asmop *aop, int offset);
76
77 int pic16_labelOffset=0;
78 extern int pic16_debug_verbose;
79 #if !(USE_GENERIC_SIGNED_SHIFT)
80 static int optimized_for_speed = 0;
81 #endif
82 /*
83   hack hack
84
85 */
86
87 extern set *externs;
88
89 /* max_key keeps track of the largest label number used in 
90    a function. This is then used to adjust the label offset
91    for the next function.
92 */
93 static int max_key=0;
94 static int GpsuedoStkPtr=0;
95
96 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
97
98 unsigned int pic16aopLiteral (value *val, int offset);
99 const char *pic16_AopType(short type);
100 static iCode *ifxForOp ( operand *op, iCode *ic );
101
102 void pic16_pushpCodeOp(pCodeOp *pcop);
103 void pic16_poppCodeOp(pCodeOp *pcop);
104
105 static bool is_LitOp(operand *op);
106 static bool is_LitAOp(asmop *aop);
107
108
109 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
110
111 /* set the following macro to 1 to enable passing the
112  * first byte of functions parameters via WREG */
113 #define USE_WREG_IN_FUNC_PARAMS 0
114
115
116 /* this is the down and dirty file with all kinds of 
117    kludgy & hacky stuff. This is what it is all about
118    CODE GENERATION for a specific MCU . some of the
119    routines may be reusable, will have to see */
120
121 static char *zero = "#0x00";
122 static char *one  = "#0x01";
123 //static char *spname = "sp";
124
125
126 /*
127  * Function return value policy (MSB-->LSB):
128  *  8 bits      -> WREG
129  * 16 bits      -> PRODL:WREG
130  * 24 bits      -> PRODH:PRODL:WREG
131  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
132  * >32 bits     -> on stack, and FSR0 points to the beginning
133  *
134  */
135  
136
137 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
138 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
139 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
140 static char **fReturn = fReturnpic16;
141
142 static char *accUse[] = {"WREG"};
143
144 //static short rbank = -1;
145
146 static struct {
147     short r0Pushed;
148     short r1Pushed;
149     short fsr0Pushed;
150     short accInUse;
151     short inLine;
152     short debugLine;
153     short nRegsSaved;
154     short ipushRegs;
155     set *sendSet;
156     set *stackRegSet;
157     int usefastretfie;
158     bitVect *fregsUsed;                 /* registers used in function */
159     bitVect *sregsAlloc;
160     set *sregsAllocSet;                 /* registers used to store stack variables */
161     int stack_lat;                      /* stack offset latency */
162     int resDirect;
163     int useWreg;                        /* flag when WREG is used to pass function parameter */
164 } _G;
165
166 extern int pic16_ptrRegReq ;
167 extern int pic16_nRegs;
168 extern FILE *codeOutFile;
169 //static void saverbank (int, iCode *,bool);
170
171 static lineNode *lineHead = NULL;
172 static lineNode *lineCurr = NULL;
173
174 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
175 0xE0, 0xC0, 0x80, 0x00};
176 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
177 0x07, 0x03, 0x01, 0x00};
178
179 static  pBlock *pb;
180
181 /*-----------------------------------------------------------------*/
182 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
183 /*                 exponent of 2 is returned, otherwise -1 is      */
184 /*                 returned.                                       */
185 /* note that this is similar to the function `powof2' in SDCCsymt  */
186 /* if(n == 2^y)                                                    */
187 /*   return y;                                                     */
188 /* return -1;                                                      */
189 /*-----------------------------------------------------------------*/
190 int pic16_my_powof2 (unsigned long num)
191 {
192   if(num) {
193     if( (num & (num-1)) == 0) {
194       int nshifts = -1;
195       while(num) {
196         num>>=1;
197         nshifts++;
198       }
199       return nshifts;
200     }
201   }
202
203   return -1;
204 }
205
206 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
207 {
208   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
209                        line_no,
210                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
211                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
212                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
213                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
214                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
215                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
216                        ((result) ? AOP_SIZE(result) : 0));
217 }
218
219 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
220 {
221
222   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
223                        line_no,
224                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
225                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
226                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
227                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
228                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
229                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
230
231 }
232
233 void pic16_emitpcomment (char *fmt, ...)
234 {
235     va_list ap;
236     char lb[INITIAL_INLINEASM];  
237     char *lbp = lb;
238
239     va_start(ap,fmt);   
240
241     lb[0] = ';';
242     vsprintf(lb+1,fmt,ap);
243
244     while (isspace(*lbp)) lbp++;
245
246     if (lbp && *lbp) 
247         lineCurr = (lineCurr ?
248                     connectLine(lineCurr,newLineNode(lb)) :
249                     (lineHead = newLineNode(lb)));
250     lineCurr->isInline = _G.inLine;
251     lineCurr->isDebug  = _G.debugLine;
252
253     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
254     va_end(ap);
255
256 //      fprintf(stderr, "%s\n", lb);
257 }
258
259 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
260 {
261     va_list ap;
262     char lb[INITIAL_INLINEASM];  
263     char *lbp = lb;
264
265     if(!pic16_debug_verbose)
266       return;
267
268     va_start(ap,fmt);   
269
270     if (inst && *inst) {
271         if (fmt && *fmt)
272             sprintf(lb,"%s\t",inst);
273         else
274             sprintf(lb,"%s",inst);
275         vsprintf(lb+(strlen(lb)),fmt,ap);
276     }  else
277         vsprintf(lb,fmt,ap);
278
279     while (isspace(*lbp)) lbp++;
280
281     if (lbp && *lbp) 
282         lineCurr = (lineCurr ?
283                     connectLine(lineCurr,newLineNode(lb)) :
284                     (lineHead = newLineNode(lb)));
285     lineCurr->isInline = _G.inLine;
286     lineCurr->isDebug  = _G.debugLine;
287
288     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
289     va_end(ap);
290
291 //      fprintf(stderr, "%s\n", lb);
292 }
293
294
295
296 void pic16_emitpLabel(int key)
297 {
298   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
299 }
300
301 void pic16_emitpLabelFORCE(int key)
302 {
303   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
304 }
305
306 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
307  * NEVER call pic16_emitpcode_real directly, please... */
308 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
309 {
310
311   if(pcop)
312     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
313   else
314     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
315 }
316
317 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
318 {
319   if(pcop)
320     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
321   else
322     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
323 }
324   
325 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
326 {
327
328   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
329
330 }
331
332
333 #if 1
334 #define pic16_emitcode  DEBUGpic16_emitcode
335 #else
336 /*-----------------------------------------------------------------*/
337 /* pic16_emitcode - writes the code into a file : for now it is simple    */
338 /*-----------------------------------------------------------------*/
339 void pic16_emitcode (char *inst,char *fmt, ...)
340 {
341     va_list ap;
342     char lb[INITIAL_INLINEASM];  
343     char *lbp = lb;
344
345     va_start(ap,fmt);   
346
347     if (inst && *inst) {
348         if (fmt && *fmt)
349             sprintf(lb,"%s\t",inst);
350         else
351             sprintf(lb,"%s",inst);
352         vsprintf(lb+(strlen(lb)),fmt,ap);
353     }  else
354         vsprintf(lb,fmt,ap);
355
356     while (isspace(*lbp)) lbp++;
357
358     if (lbp && *lbp) 
359         lineCurr = (lineCurr ?
360                     connectLine(lineCurr,newLineNode(lb)) :
361                     (lineHead = newLineNode(lb)));
362     lineCurr->isInline = _G.inLine;
363     lineCurr->isDebug  = _G.debugLine;
364
365 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
366
367 //    if(pic16_debug_verbose)
368 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
369
370     va_end(ap);
371 }
372 #endif
373
374
375 /*-----------------------------------------------------------------*/
376 /* pic16_emitDebuggerSymbol - associate the current code location  */
377 /*   with a debugger symbol                                        */
378 /*-----------------------------------------------------------------*/
379 void
380 pic16_emitDebuggerSymbol (char * debugSym)
381 {
382   _G.debugLine = 1;
383   pic16_emitcode (";", "%s ==.", debugSym);
384   _G.debugLine = 0;
385 }
386
387
388 /*-----------------------------------------------------------------*/
389 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
390 /*-----------------------------------------------------------------*/
391 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
392 {
393 //    bool r0iu = FALSE , r1iu = FALSE;
394 //    bool r0ou = FALSE , r1ou = FALSE;
395     bool fsr0iu = FALSE, fsr0ou;
396     bool fsr2iu = FALSE, fsr2ou;
397     
398     fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
399
400     
401     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
402     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
403     
404     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
405     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
406
407     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
408         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
409         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
410     }
411
412     if(!fsr0iu && !fsr0ou) {
413         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
414         (*aopp)->type = AOP_FSR0;
415
416         fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
417         
418       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
419     }
420
421 #if 0
422     /* no usage of FSR2 */
423     if(!fsr2iu && !fsr2ou) {
424         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
425         (*aopp)->type = AOP_FSR2;
426
427       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
428     }
429 #endif
430         
431     /* now we know they both have usage */
432     /* if fsr0 not used in this instruction */
433     if (!fsr0iu) {
434         if (!_G.fsr0Pushed) {
435                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
436                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
437                 _G.fsr0Pushed++;
438         }
439
440         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
441         (*aopp)->type = AOP_FSR0;
442
443 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
444
445       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
446     }
447         
448
449     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
450     assert( 0 );
451
452     return NULL;
453 #if 0
454     /* the logic: if r0 & r1 used in the instruction
455     then we are in trouble otherwise */
456
457     /* first check if r0 & r1 are used by this
458     instruction, in which case we are in trouble */
459     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
460         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
461     {
462         goto endOfWorld;      
463     }
464
465     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
466     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
467
468     /* if no usage of r0 then return it */
469     if (!r0iu && !r0ou) {
470         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
471         (*aopp)->type = AOP_R0; 
472         
473         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
474     }
475
476     /* if no usage of r1 then return it */
477     if (!r1iu && !r1ou) {
478         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
479         (*aopp)->type = AOP_R1;
480
481         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
482     }    
483
484     /* now we know they both have usage */
485     /* if r0 not used in this instruction */
486     if (!r0iu) {
487         /* push it if not already pushed */
488         if (!_G.r0Pushed) {
489           //pic16_emitcode ("push","%s",
490           //          pic16_regWithIdx(R0_IDX)->dname);
491             _G.r0Pushed++ ;
492         }
493         
494         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
495         (*aopp)->type = AOP_R0;
496
497         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
498     }
499
500     /* if r1 not used then */
501
502     if (!r1iu) {
503         /* push it if not already pushed */
504         if (!_G.r1Pushed) {
505           //pic16_emitcode ("push","%s",
506           //          pic16_regWithIdx(R1_IDX)->dname);
507             _G.r1Pushed++ ;
508         }
509         
510         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
511         (*aopp)->type = AOP_R1;
512         return pic16_regWithIdx(R1_IDX);
513     }
514
515 endOfWorld :
516     /* I said end of world but not quite end of world yet */
517     /* if this is a result then we can push it on the stack*/
518     if (result) {
519         (*aopp)->type = AOP_STK;    
520         return NULL;
521     }
522
523     /* other wise this is true end of the world */
524     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
525            "getFreePtr should never reach here");
526     exit(0);
527 #endif
528 }
529
530 /*-----------------------------------------------------------------*/
531 /* newAsmop - creates a new asmOp                                  */
532 /*-----------------------------------------------------------------*/
533 static asmop *newAsmop (short type)
534 {
535     asmop *aop;
536
537     aop = Safe_calloc(1,sizeof(asmop));
538     aop->type = type;
539     return aop;
540 }
541
542 static void genSetDPTR(int n)
543 {
544     if (!n)
545     {
546         pic16_emitcode(";", "Select standard DPTR");
547         pic16_emitcode("mov", "dps, #0x00");
548     }
549     else
550     {
551         pic16_emitcode(";", "Select alternate DPTR");
552         pic16_emitcode("mov", "dps, #0x01");
553     }
554 }
555
556 /*-----------------------------------------------------------------*/
557 /* resolveIfx - converts an iCode ifx into a form more useful for  */
558 /*              generating code                                    */
559 /*-----------------------------------------------------------------*/
560 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
561 {
562   FENTRY2;
563   
564 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
565
566   if(!resIfx) 
567     return;
568
569
570   resIfx->condition = 1;    /* assume that the ifx is true */
571   resIfx->generated = 0;    /* indicate that the ifx has not been used */
572
573   if(!ifx) {
574     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
575
576 #if 1
577     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
578                         __FUNCTION__,__LINE__,resIfx->lbl->key);
579 #endif
580
581   } else {
582     if(IC_TRUE(ifx)) {
583       resIfx->lbl = IC_TRUE(ifx);
584     } else {
585       resIfx->lbl = IC_FALSE(ifx);
586       resIfx->condition = 0;
587     }
588
589 #if 1
590     if(IC_TRUE(ifx)) 
591       DEBUGpic16_emitcode("; +++","ifx true is non-null");
592     else
593       DEBUGpic16_emitcode("; +++","ifx true is null");
594     if(IC_FALSE(ifx)) 
595       DEBUGpic16_emitcode("; +++","ifx false is non-null");
596     else
597       DEBUGpic16_emitcode("; +++","ifx false is null");
598 #endif
599   }
600
601   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
602
603 }
604 #if 0
605 /*-----------------------------------------------------------------*/
606 /* pointerCode - returns the code for a pointer type               */
607 /*-----------------------------------------------------------------*/
608 static int pointerCode (sym_link *etype)
609 {
610
611     return PTR_TYPE(SPEC_OCLS(etype));
612
613 }
614 #endif
615
616 /*-----------------------------------------------------------------*/
617 /* aopForSym - for a true symbol                                   */
618 /*-----------------------------------------------------------------*/
619 static asmop *aopForSym (iCode *ic, operand *op, bool result)
620 {
621     symbol *sym=OP_SYMBOL(op);
622     asmop *aop;
623     memmap *space= SPEC_OCLS(sym->etype);
624
625     FENTRY2;
626     
627     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
628     
629 //    sym = OP_SYMBOL(op);
630
631     /* if already has one */
632     if (sym->aop) {
633             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
634         return sym->aop;
635     }
636
637 #if 0
638     /* if symbol was initially placed onStack then we must re-place it
639      * to direct memory, since pic16 does not have a specific stack */
640     if(sym->onStack) {
641         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
642     }
643 #endif
644
645
646 #if 0
647     if(sym->iaccess) {
648       if(space->paged) {
649         fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
650
651         sym->aop = aop = newAsmop (AOP_PAGED);
652         aop->aopu.aop_dir = sym->rname ;
653         aop->size = getSize(sym->type);
654         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
655         pic16_allocDirReg( IC_LEFT(ic) );
656         return aop;
657       }
658       assert( 0 );
659     }
660 #endif
661     
662 #if 1
663     /* assign depending on the storage class */
664     /* if it is on the stack or indirectly addressable */
665     /* space we need to assign either r0 or r1 to it   */    
666     if (sym->onStack)   // || sym->iaccess)
667     {
668       pCodeOp *pcop[4];
669       int i;
670       
671         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
672                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
673         
674         /* acquire a temporary register -- it is saved in function */
675
676         sym->aop = aop = newAsmop(AOP_STA);
677         aop->aopu.stk.stk = sym->stack;
678         aop->size = getSize(sym->type);
679
680
681         DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
682         if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
683           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
684 //          pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
685           
686           for(i=0;i<aop->size;i++)
687             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
688             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
689         } else
690         if(1 && ic->op == SEND) {
691
692           /* if SEND do the send here */
693           _G.resDirect = 1;
694         } else {
695           for(i=0;i<aop->size;i++) {
696             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
697             _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
698           }
699         }
700
701
702 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
703
704 #if 1
705         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
706
707         // we do not need to load the value if it is to be defined...
708         if (result) return aop;
709
710         if(_G.accInUse) {
711                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
712         }
713         
714         for(i=0;i<aop->size;i++) {
715
716           /* initialise for stack access via frame pointer */
717           // operands on stack are accessible via "FSR2 + index" with index
718           // starting at 2 for arguments and growing from 0 downwards for
719           // local variables (index == 0 is not assigned so we add one here)
720           {
721             int soffs = sym->stack;
722             if (soffs <= 0) {
723               assert (soffs < 0);
724               soffs++;
725             } // if
726
727             if(1 && ic->op == SEND) {
728               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
729               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
730                     pic16_popCopyReg( pic16_frame_plusw ),
731                     pic16_popCopyReg(pic16_stack_postdec )));
732             } else {
733               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
734               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
735                   pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
736             }
737           }
738         }
739         
740         if(_G.accInUse) {
741                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
742         }
743         
744         return (aop);
745 #endif
746
747 #if 0
748         /* now assign the address of the variable to 
749         the pointer register */
750         if (aop->type != AOP_STK) {
751
752             if (sym->onStack) {
753                     if ( _G.accInUse )
754                         pic16_emitcode("push","acc");
755
756                     pic16_emitcode("mov","a,_bp");
757                     pic16_emitcode("add","a,#0x%02x",
758                              ((sym->stack < 0) ?
759                               ((char)(sym->stack - _G.nRegsSaved )) :
760                               ((char)sym->stack)) & 0xff);
761                     pic16_emitcode("mov","%s,a",
762                              aop->aopu.aop_ptr->name);
763
764                     if ( _G.accInUse )
765                         pic16_emitcode("pop","acc");
766             } else
767                 pic16_emitcode("mov","%s,#%s",
768                          aop->aopu.aop_ptr->name,
769                          sym->rname);
770             aop->paged = space->paged;
771         } else
772             aop->aopu.aop_stk = sym->stack;
773         return aop;
774 #endif
775
776     }
777 #endif
778
779 #if 0
780     if (sym->onStack && options.stack10bit)
781     {
782         /* It's on the 10 bit stack, which is located in
783          * far data space.
784          */
785          
786       //DEBUGpic16_emitcode(";","%d",__LINE__);
787
788         if ( _G.accInUse )
789                 pic16_emitcode("push","acc");
790
791         pic16_emitcode("mov","a,_bp");
792         pic16_emitcode("add","a,#0x%02x",
793                  ((sym->stack < 0) ?
794                    ((char)(sym->stack - _G.nRegsSaved )) :
795                    ((char)sym->stack)) & 0xff);
796         
797         genSetDPTR(1);
798         pic16_emitcode ("mov","dpx1,#0x40");
799         pic16_emitcode ("mov","dph1,#0x00");
800         pic16_emitcode ("mov","dpl1, a");
801         genSetDPTR(0);
802         
803         if ( _G.accInUse )
804             pic16_emitcode("pop","acc");
805             
806         sym->aop = aop = newAsmop(AOP_DPTR2);
807         aop->size = getSize(sym->type); 
808         return aop;
809     }
810 #endif
811
812 #if 1
813     /* special case for a function */
814     if (IS_FUNC(sym->type)) {   
815         sym->aop = aop = newAsmop(AOP_PCODE);
816         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
817         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
818         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
819         PCOI(aop->aopu.pcop)->index = 0;
820         aop->size = FPTRSIZE; 
821         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
822         return aop;
823     }
824 #endif
825
826
827
828     //DEBUGpic16_emitcode(";","%d",__LINE__);
829     /* if in bit space */
830     if (IN_BITSPACE(space)) {
831         sym->aop = aop = newAsmop (AOP_CRY);
832         aop->aopu.aop_dir = sym->rname ;
833         aop->size = getSize(sym->type);
834         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
835         return aop;
836     }
837     /* if it is in direct space */
838     if (IN_DIRSPACE(space)) {
839         sym->aop = aop = newAsmop (AOP_DIR);
840         aop->aopu.aop_dir = sym->rname ;
841         aop->size = getSize(sym->type);
842         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
843         pic16_allocDirReg( IC_LEFT(ic) );
844         return aop;
845     }
846
847
848     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
849         sym->aop = aop = newAsmop (AOP_DIR);
850         aop->aopu.aop_dir = sym->rname ;
851         aop->size = getSize(sym->type);
852         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
853         pic16_allocDirReg( IC_LEFT(ic) );
854         return aop;
855     }
856
857
858     /* only remaining is far space */
859     sym->aop = aop = newAsmop(AOP_PCODE);
860
861 /* change the next if to 1 to revert to good old immediate code */
862         if(IN_CODESPACE(space)) {
863                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
864                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
865                 PCOI(aop->aopu.pcop)->index = 0;
866         } else {
867                 /* try to allocate via direct register */
868                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
869 //              aop->size = getSize( sym->type );
870         }
871
872         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
873                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
874
875 #if 0
876         if(!pic16_allocDirReg (IC_LEFT(ic)))
877                 return NULL;
878 #endif
879
880         if(IN_DIRSPACE( space ))
881                 aop->size = PTRSIZE;
882         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
883                 aop->size = FPTRSIZE;
884         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
885         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
886         else if(sym->onStack) {
887                 aop->size = PTRSIZE;
888         } else {
889           if(SPEC_SCLS(sym->etype) == S_PDATA) {
890             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
891             aop->size = FPTRSIZE;
892           } else
893                 assert( 0 );
894         }
895
896     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
897
898     /* if it is in code space */
899     if (IN_CODESPACE(space))
900         aop->code = 1;
901
902     return aop;     
903 }
904
905 /*-----------------------------------------------------------------*/
906 /* aopForRemat - rematerialzes an object                           */
907 /*-----------------------------------------------------------------*/
908 static asmop *aopForRemat (operand *op) // x symbol *sym)
909 {
910   symbol *sym = OP_SYMBOL(op);
911   operand *refop;
912   iCode *ic = NULL, *oldic;
913   asmop *aop = newAsmop(AOP_PCODE);
914   int val = 0;
915   int offset = 0;
916   int viaimmd=0;
917
918     FENTRY2;
919     
920         ic = sym->rematiCode;
921
922         if(IS_OP_POINTER(op)) {
923                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
924         }
925
926         for (;;) {
927                 oldic = ic;
928
929 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
930         
931                 if (ic->op == '+') {
932                         val += (int) operandLitValue(IC_RIGHT(ic));
933                 } else if (ic->op == '-') {
934                         val -= (int) operandLitValue(IC_RIGHT(ic));
935                 } else
936                         break;
937                 
938                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
939         }
940
941         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
942         refop = IC_LEFT(ic);
943
944         if(!op->isaddr)viaimmd++; else viaimmd=0;
945                 
946 /* set the following if to 1 to revert to good old immediate code */
947         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
948                 || viaimmd) {
949
950                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
951
952                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
953
954 #if 0
955                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
956 #else
957                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
958 #endif
959
960                 PCOI(aop->aopu.pcop)->index = val;
961                 
962                 aop->size = getSize( sym->type );
963         } else {
964                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
965
966                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
967                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
968
969                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
970         }
971
972
973         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
974                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
975 #if 0
976                 val, IS_PTR_CONST(operandType(op)));
977 #else
978                 val, IS_CODEPTR(operandType(op)));
979 #endif
980
981 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
982
983         pic16_allocDirReg (IC_LEFT(ic));
984
985         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
986                 aop->code = 1;
987
988   return aop;        
989 }
990
991 #if 0
992 static int aopIdx (asmop *aop, int offset)
993 {
994   if(!aop)
995     return -1;
996
997   if(aop->type !=  AOP_REG)
998     return -2;
999         
1000   return aop->aopu.aop_reg[offset]->rIdx;
1001
1002 }
1003 #endif
1004
1005 /*-----------------------------------------------------------------*/
1006 /* regsInCommon - two operands have some registers in common       */
1007 /*-----------------------------------------------------------------*/
1008 static bool regsInCommon (operand *op1, operand *op2)
1009 {
1010     symbol *sym1, *sym2;
1011     int i;
1012
1013     /* if they have registers in common */
1014     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1015         return FALSE ;
1016
1017     sym1 = OP_SYMBOL(op1);
1018     sym2 = OP_SYMBOL(op2);
1019
1020     if (sym1->nRegs == 0 || sym2->nRegs == 0)
1021         return FALSE ;
1022
1023     for (i = 0 ; i < sym1->nRegs ; i++) {
1024         int j;
1025         if (!sym1->regs[i])
1026             continue ;
1027
1028         for (j = 0 ; j < sym2->nRegs ;j++ ) {
1029             if (!sym2->regs[j])
1030                 continue ;
1031
1032             if (sym2->regs[j] == sym1->regs[i])
1033                 return TRUE ;
1034         }
1035     }
1036
1037     return FALSE ;
1038 }
1039
1040 /*-----------------------------------------------------------------*/
1041 /* operandsEqu - equivalent                                        */
1042 /*-----------------------------------------------------------------*/
1043 static bool operandsEqu ( operand *op1, operand *op2)
1044 {
1045     symbol *sym1, *sym2;
1046
1047     /* if they not symbols */
1048     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1049         return FALSE;
1050
1051     sym1 = OP_SYMBOL(op1);
1052     sym2 = OP_SYMBOL(op2);
1053
1054     /* if both are itemps & one is spilt
1055        and the other is not then false */
1056     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1057         sym1->isspilt != sym2->isspilt )
1058         return FALSE ;
1059
1060     /* if they are the same */
1061     if (sym1 == sym2)
1062         return TRUE ;
1063
1064     if (sym1->rname[0] && sym2->rname[0]
1065         && strcmp (sym1->rname, sym2->rname) == 0)
1066         return TRUE;
1067
1068
1069     /* if left is a tmp & right is not */
1070     if (IS_ITEMP(op1)  && 
1071         !IS_ITEMP(op2) &&
1072         sym1->isspilt  &&
1073         (sym1->usl.spillLoc == sym2))
1074         return TRUE;
1075
1076     if (IS_ITEMP(op2)  && 
1077         !IS_ITEMP(op1) &&
1078         sym2->isspilt  &&
1079         sym1->level > 0 &&
1080         (sym2->usl.spillLoc == sym1))
1081         return TRUE ;
1082
1083     return FALSE ;
1084 }
1085
1086 /*-----------------------------------------------------------------*/
1087 /* pic16_sameRegs - two asmops have the same registers                   */
1088 /*-----------------------------------------------------------------*/
1089 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1090 {
1091     int i;
1092
1093     if (aop1 == aop2)
1094         return TRUE ;
1095
1096     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1097                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1098
1099     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1100
1101     if (aop1->type != AOP_REG ||
1102         aop2->type != AOP_REG )
1103         return FALSE ;
1104
1105     /* This is a bit too restrictive if one is a subset of the other...
1106     if (aop1->size != aop2->size )
1107         return FALSE ;
1108     */
1109
1110     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1111 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1112
1113 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1114         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1115             return FALSE ;
1116     }
1117
1118     return TRUE ;
1119 }
1120
1121 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1122 {
1123     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1124                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1125
1126     if(aop1 == aop2)return TRUE;
1127     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1128       
1129       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1130     
1131   return TRUE;
1132 }
1133
1134
1135 /*-----------------------------------------------------------------*/
1136 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1137 /*-----------------------------------------------------------------*/
1138 void pic16_aopOp (operand *op, iCode *ic, bool result)
1139 {
1140     asmop *aop;
1141     symbol *sym;
1142     int i;
1143
1144     if (!op)
1145         return ;
1146
1147     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1148
1149     /* if this a literal */
1150     if (IS_OP_LITERAL(op)) {
1151         op->aop = aop = newAsmop(AOP_LIT);
1152         aop->aopu.aop_lit = op->operand.valOperand;
1153         aop->size = getSize(operandType(op));
1154         return;
1155     }
1156
1157     {
1158       sym_link *type = operandType(op);
1159 #if 0
1160       if(IS_PTR_CONST(type))
1161 #else
1162       if(IS_CODEPTR(type))
1163 #endif
1164         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1165     }
1166
1167     /* if already has a asmop then continue */
1168     if (op->aop)
1169         return ;
1170
1171     /* if the underlying symbol has a aop */
1172     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1173       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1174         op->aop = OP_SYMBOL(op)->aop;
1175         return;
1176     }
1177
1178     /* if this is a true symbol */
1179     if (IS_TRUE_SYMOP(op)) {    
1180         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1181       op->aop = aopForSym(ic, op, result);
1182       return ;
1183     }
1184
1185     /* this is a temporary : this has
1186     only four choices :
1187     a) register
1188     b) spillocation
1189     c) rematerialize 
1190     d) conditional   
1191     e) can be a return use only */
1192
1193     sym = OP_SYMBOL(op);
1194
1195     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1196     /* if the type is a conditional */
1197     if (sym->regType == REG_CND) {
1198         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1199         aop->size = 0;
1200         return;
1201     }
1202
1203     /* if it is spilt then two situations
1204     a) is rematerialize 
1205     b) has a spill location */
1206     if (sym->isspilt || sym->nRegs == 0) {
1207
1208 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1209       DEBUGpic16_emitcode(";","%d",__LINE__);
1210         /* rematerialize it NOW */
1211         if (sym->remat) {
1212
1213             sym->aop = op->aop = aop = aopForRemat (op);
1214 //            aop->size = getSize(sym->type);
1215 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1216             return;
1217         }
1218
1219 #if 1
1220         if (sym->accuse) {
1221             int i;
1222             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1223             aop->size = getSize(sym->type);
1224             for ( i = 0 ; i < 1 ; i++ ) {
1225                 aop->aopu.aop_str[i] = accUse[i];
1226 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1227             }
1228             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1229             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1230             return;  
1231         }
1232 #endif
1233
1234 #if 1
1235         if (sym->ruonly) {
1236           /*
1237           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1238           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1239           //pic16_allocDirReg (IC_LEFT(ic));
1240           aop->size = getSize(sym->type);
1241           */
1242
1243           unsigned i;
1244
1245           aop = op->aop = sym->aop = newAsmop(AOP_REG);
1246           aop->size = getSize(sym->type);
1247           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1248             aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1249
1250           DEBUGpic16_emitcode(";","%d",__LINE__);
1251           return;
1252         }
1253 #endif
1254         /* else spill location  */
1255         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1256             /* force a new aop if sizes differ */
1257             sym->usl.spillLoc->aop = NULL;
1258         }
1259
1260 #if 0
1261         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1262                             __FUNCTION__,__LINE__,
1263                             sym->usl.spillLoc->rname,
1264                             sym->rname, sym->usl.spillLoc->offset);
1265 #endif
1266
1267         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1268         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1269         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1270           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1271                                                   getSize(sym->type), 
1272                                                   sym->usl.spillLoc->offset, op);
1273         } else {
1274           fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1275           pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1276           assert (getSize(sym->type) <= 1);
1277           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1278         }
1279         aop->size = getSize(sym->type);
1280
1281         return;
1282     }
1283
1284     {
1285       sym_link *type = operandType(op);
1286 #if 0
1287       if(IS_PTR_CONST(type)) 
1288 #else
1289       if(IS_CODEPTR(type)) 
1290 #endif
1291         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1292     }
1293
1294     /* must be in a register */
1295     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1296     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1297     aop->size = sym->nRegs;
1298     for ( i = 0 ; i < sym->nRegs ;i++)
1299         aop->aopu.aop_reg[i] = sym->regs[i];
1300 }
1301
1302 /*-----------------------------------------------------------------*/
1303 /* pic16_freeAsmop - free up the asmop given to an operand               */
1304 /*----------------------------------------------------------------*/
1305 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1306 {   
1307     asmop *aop ;
1308
1309     if (!op)
1310         aop = aaop;
1311     else 
1312         aop = op->aop;
1313
1314     if (!aop)
1315         return ;
1316
1317     if (aop->freed)
1318         goto dealloc; 
1319
1320     aop->freed = 1;
1321
1322     /* depending on the asmop type only three cases need work AOP_RO
1323        , AOP_R1 && AOP_STK */
1324 #if 1
1325     switch (aop->type) {
1326         case AOP_FSR0 :
1327             if (_G.fsr0Pushed ) {
1328                 if (pop) {
1329                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1330                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1331 //                    pic16_emitcode ("pop","ar0");
1332                     _G.fsr0Pushed--;
1333                 }
1334             }
1335             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1336             break;
1337
1338         case AOP_FSR2 :
1339             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1340             break;
1341
1342         case AOP_R0 :
1343             if (_G.r0Pushed ) {
1344                 if (pop) {
1345                     pic16_emitcode ("pop","ar0");     
1346                     _G.r0Pushed--;
1347                 }
1348             }
1349             bitVectUnSetBit(ic->rUsed,R0_IDX);
1350             break;
1351
1352         case AOP_R1 :
1353             if (_G.r1Pushed ) {
1354                 if (pop) {
1355                     pic16_emitcode ("pop","ar1");
1356                     _G.r1Pushed--;
1357                 }
1358             }
1359             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1360             break;
1361
1362         case AOP_STA:
1363           {
1364             int i;
1365
1366               /* we must store the result on stack */
1367               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1368                 // operands on stack are accessible via "FSR2 + index" with index
1369                 // starting at 2 for arguments and growing from 0 downwards for
1370                 // local variables (index == 0 is not assigned so we add one here)
1371                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1372                 if (soffs <= 0) {
1373                   assert (soffs < 0);
1374                   soffs++;
1375                 } // if
1376                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1377                 for(i=0;i<aop->size;i++) {
1378                   /* initialise for stack access via frame pointer */
1379                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1380                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1381                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1382                 }
1383         
1384                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1385               }
1386
1387               if(!_G.resDirect) {
1388                 for(i=0;i<aop->size;i++) {
1389                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1390
1391                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx))
1392                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1393                 }
1394                   
1395               }
1396               _G.resDirect = 0;
1397           }
1398           break;
1399 #if 0
1400         case AOP_STK :
1401         {
1402             int sz = aop->size;    
1403             int stk = aop->aopu.aop_stk + aop->size;
1404             bitVectUnSetBit(ic->rUsed,R0_IDX);
1405             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1406
1407             getFreePtr(ic,&aop,FALSE);
1408             
1409             if (options.stack10bit)
1410             {
1411                 /* I'm not sure what to do here yet... */
1412                 /* #STUB */
1413                 fprintf(stderr, 
1414                         "*** Warning: probably generating bad code for "
1415                         "10 bit stack mode.\n");
1416             }
1417             
1418             if (stk) {
1419                 pic16_emitcode ("mov","a,_bp");
1420                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1421                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1422             } else {
1423                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1424             }
1425
1426             while (sz--) {
1427                 pic16_emitcode("pop","acc");
1428                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1429                 if (!sz) break;
1430                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1431             }
1432             op->aop = aop;
1433             pic16_freeAsmop(op,NULL,ic,TRUE);
1434             if (_G.r0Pushed) {
1435                 pic16_emitcode("pop","ar0");
1436                 _G.r0Pushed--;
1437             }
1438
1439             if (_G.r1Pushed) {
1440                 pic16_emitcode("pop","ar1");
1441                 _G.r1Pushed--;
1442             }       
1443         }
1444 #endif
1445
1446     }
1447 #endif
1448
1449 dealloc:
1450     /* all other cases just dealloc */
1451     if (op ) {
1452         op->aop = NULL;
1453         if (IS_SYMOP(op)) {
1454             OP_SYMBOL(op)->aop = NULL;    
1455             /* if the symbol has a spill */
1456             if (SPIL_LOC(op))
1457                 SPIL_LOC(op)->aop = NULL;
1458         }
1459     }
1460 }
1461
1462 /*-----------------------------------------------------------------*/
1463 /* pic16_aopGet - for fetching value of the aop                          */
1464 /*-----------------------------------------------------------------*/
1465 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1466 {
1467     char *s = buffer ;
1468     char *rs;
1469
1470     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1471
1472     /* offset is greater than size then zero */
1473     if (offset > (aop->size - 1) &&
1474         aop->type != AOP_LIT)
1475         return zero;
1476
1477     /* depending on type */
1478     switch (aop->type) {
1479
1480     case AOP_FSR0:
1481     case AOP_FSR2:
1482       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1483       rs = Safe_calloc(1, strlen(s)+1);
1484       strcpy(rs, s);
1485       return (rs);
1486       
1487 #if 0
1488       /* if we need to increment it */
1489       while (offset > aop->coff)
1490         {
1491           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1492           aop->coff++;
1493         }
1494
1495       while (offset < aop->coff)
1496         {
1497           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1498           aop->coff--;
1499         }
1500       aop->coff = offset;
1501       if (aop->paged)
1502         {
1503           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1504           return (dname ? "acc" : "a");
1505         }
1506       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1507       rs = Safe_calloc (1, strlen (s) + 1);
1508       strcpy (rs, s);
1509       return rs;
1510 #endif
1511
1512         
1513     case AOP_IMMD:
1514         if (bit16) 
1515             sprintf (s,"%s",aop->aopu.aop_immd);
1516         else
1517             if (offset) 
1518                 sprintf(s,"(%s >> %d)",
1519                         aop->aopu.aop_immd,
1520                         offset*8);
1521             else
1522                 sprintf(s,"%s",
1523                         aop->aopu.aop_immd);
1524         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1525         rs = Safe_calloc(1,strlen(s)+1);
1526         strcpy(rs,s);   
1527         return rs;
1528         
1529     case AOP_DIR:
1530       if (offset) {
1531         sprintf(s,"(%s + %d)",
1532                 aop->aopu.aop_dir,
1533                 offset);
1534         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1535       } else
1536             sprintf(s,"%s",aop->aopu.aop_dir);
1537         rs = Safe_calloc(1,strlen(s)+1);
1538         strcpy(rs,s);   
1539         return rs;
1540         
1541     case AOP_REG:
1542       //if (dname) 
1543       //    return aop->aopu.aop_reg[offset]->dname;
1544       //else
1545             return aop->aopu.aop_reg[offset]->name;
1546         
1547     case AOP_CRY:
1548       //pic16_emitcode(";","%d",__LINE__);
1549       return aop->aopu.aop_dir;
1550         
1551     case AOP_ACC:
1552         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1553 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1554 //        assert( 0 );
1555 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1556         rs = Safe_strdup("WREG");
1557         return (rs);
1558
1559     case AOP_LIT:
1560         sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1561         rs = Safe_calloc(1,strlen(s)+1);
1562         strcpy(rs,s);   
1563         return rs;
1564         
1565     case AOP_STR:
1566         aop->coff = offset ;
1567
1568 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1569 //          dname)
1570 //          return "acc";
1571         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1572           aop->type = AOP_ACC;
1573           return Safe_strdup("WREG");
1574         }
1575         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1576         
1577         return aop->aopu.aop_str[offset];
1578         
1579     case AOP_PCODE:
1580       {
1581         pCodeOp *pcop = aop->aopu.pcop;
1582         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1583         if(pcop->name) {
1584           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1585           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1586           if (offset) {
1587             sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1588           } else {
1589             sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1590           }
1591         } else
1592           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1593
1594       }
1595       rs = Safe_calloc(1,strlen(s)+1);
1596       strcpy(rs,s);   
1597       return rs;
1598
1599 #if 0
1600     case AOP_PAGED:
1601       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1602       if (offset) {
1603         sprintf(s,"(%s + %d)",
1604                 aop->aopu.aop_dir,
1605                 offset);
1606       } else
1607             sprintf(s,"%s",aop->aopu.aop_dir);
1608       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1609       rs = Safe_calloc(1,strlen(s)+1);
1610       strcpy(rs,s);   
1611       return rs;
1612 #endif
1613
1614     case AOP_STA:
1615         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1616         return (rs);
1617         
1618     case AOP_STK:
1619 //        pCodeOp *pcop = aop->aop
1620         break;
1621
1622     }
1623
1624     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1625     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1626            "aopget got unsupported aop->type");
1627     exit(0);
1628 }
1629
1630
1631
1632 /* lock has the following meaning: When allocating temporary registers
1633  * for stack variables storage, the value of the temporary register is
1634  * saved on stack. Its value is restored at the end. This procedure is
1635  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1636  * a possibility that before a call to pic16_aopOp, a temporary register
1637  * is allocated for a while and it is freed after some time, this will
1638  * mess the stack and values will not be restored properly. So use lock=1
1639  * to allocate temporary registers used internally by the programmer, and
1640  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1641  * to inform the compiler developer about a possible bug. This is an internal
1642  * feature for developing the compiler -- VR */
1643  
1644 int _TempReg_lock = 0;
1645 /*-----------------------------------------------------------------*/
1646 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1647 /*-----------------------------------------------------------------*/
1648 pCodeOp *pic16_popGetTempReg(int lock)
1649 {
1650   pCodeOp *pcop;
1651   symbol *cfunc;
1652
1653 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1654     if(_TempReg_lock) {
1655 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1656     }
1657     
1658     _TempReg_lock += lock;
1659     
1660     cfunc = currFunc;
1661     currFunc = NULL;
1662
1663     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1664     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1665       PCOR(pcop)->r->wasUsed=1;
1666       PCOR(pcop)->r->isFree=0;
1667
1668       /* push value on stack */
1669       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1670     }
1671
1672     currFunc = cfunc;
1673
1674   return pcop;
1675 }
1676
1677 /*-----------------------------------------------------------------*/
1678 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1679 /*                           is not part of f, but don't save if   */
1680 /*                           inside v                              */
1681 /*-----------------------------------------------------------------*/
1682 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1683 {
1684   pCodeOp *pcop=NULL;
1685   symbol *cfunc;
1686   int i;
1687
1688 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1689
1690     if(_TempReg_lock) {
1691 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1692     }
1693
1694     _TempReg_lock += lock;
1695
1696     cfunc = currFunc;
1697     currFunc = NULL;
1698
1699     i = bitVectFirstBit(f);
1700     while(i < 128) {
1701
1702       /* bypass registers that are used by function */
1703       if(!bitVectBitValue(f, i)) {
1704       
1705         /* bypass registers that are already allocated for stack access */
1706         if(!bitVectBitValue(v, i))  {
1707         
1708 //          debugf("getting register rIdx = %d\n", i);
1709           /* ok, get the operand */
1710           pcop = pic16_newpCodeOpReg( i );
1711     
1712           /* should never by NULL */
1713           assert( pcop != NULL );
1714
1715           
1716           /* sanity check */
1717           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1718             int found=0;
1719             
1720               PCOR(pcop)->r->wasUsed=1;
1721               PCOR(pcop)->r->isFree=0;
1722
1723
1724               {
1725                 regs *sr;
1726               
1727                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1728
1729                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1730                       /* already used in previous steps, break */
1731                       found=1;          
1732                       break;
1733                     }
1734                   }
1735               }
1736
1737               /* caller takes care of the following */
1738 //              bitVectSetBit(v, i);
1739
1740               if(!found) {
1741                 /* push value on stack */
1742                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1743                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1744               }
1745           
1746             break;
1747           }
1748         }
1749       }
1750       i++;
1751     }
1752
1753     currFunc = cfunc;
1754
1755   return pcop;
1756 }
1757
1758
1759 /*-----------------------------------------------------------------*/
1760 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1761 /*-----------------------------------------------------------------*/
1762 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1763 {
1764   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1765
1766   _TempReg_lock -= lock;
1767
1768   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1769     PCOR(pcop)->r->isFree = 1;
1770
1771     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1772   }
1773 }
1774 /*-----------------------------------------------------------------*/
1775 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1776 /*-----------------------------------------------------------------*/
1777 pCodeOp *pic16_popGetLabel(unsigned int key)
1778 {
1779
1780   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1781
1782   if(key>max_key)
1783     max_key = key;
1784
1785   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1786 }
1787
1788 /*-----------------------------------------------------------------*/
1789 /* pic16_popCopyReg - copy a pcode operator                              */
1790 /*-----------------------------------------------------------------*/
1791 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1792 {
1793   pCodeOpReg *pcor;
1794
1795   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1796   memcpy (pcor, pc, sizeof (pCodeOpReg));
1797   pcor->r->wasUsed = 1;
1798   
1799   //pcor->pcop.type = pc->pcop.type;
1800   if(pc->pcop.name) {
1801     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1802       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1803   } else
1804     pcor->pcop.name = NULL;
1805
1806   //pcor->r = pc->r;
1807   //pcor->rIdx = pc->rIdx;
1808   //pcor->r->wasUsed=1;
1809   //pcor->instance = pc->instance;
1810
1811 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1812
1813   return PCOP(pcor);
1814 }
1815
1816 /*-----------------------------------------------------------------*/
1817 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1818 /*-----------------------------------------------------------------*/
1819 pCodeOp *pic16_popGetLit(int lit)
1820 {
1821   return pic16_newpCodeOpLit(lit);
1822 }
1823
1824 /*-----------------------------------------------------------------*/
1825 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1826 /*-----------------------------------------------------------------*/
1827 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1828 {
1829   return pic16_newpCodeOpLit2(lit, arg2);
1830 }
1831
1832
1833 /*-----------------------------------------------------------------*/
1834 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1835 /*-----------------------------------------------------------------*/
1836 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1837 {
1838   return pic16_newpCodeOpImmd(name, offset,index, 0);
1839 }
1840
1841
1842 /*-----------------------------------------------------------------*/
1843 /* pic16_popGet - asm operator to pcode operator conversion              */
1844 /*-----------------------------------------------------------------*/
1845 pCodeOp *pic16_popGetWithString(char *str)
1846 {
1847   pCodeOp *pcop;
1848
1849
1850   if(!str) {
1851     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1852     exit (1);
1853   }
1854
1855   pcop = pic16_newpCodeOp(str,PO_STR);
1856
1857   return pcop;
1858 }
1859
1860 /*-----------------------------------------------------------------*/
1861 /* pic16_popRegFromString -                                        */
1862 /*-----------------------------------------------------------------*/
1863 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1864 {
1865
1866   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1867   pcop->type = PO_DIR;
1868
1869   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1870   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1871
1872   if(!str)
1873     str = "BAD_STRING";
1874
1875   pcop->name = Safe_calloc(1,strlen(str)+1);
1876   strcpy(pcop->name,str);
1877
1878   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1879
1880   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1881
1882   /* make sure that register doesn't exist,
1883    * and operand isn't NULL
1884    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1885   if((PCOR(pcop)->r == NULL) 
1886     && (op)
1887     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1888 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1889 //              __FUNCTION__, __LINE__, str, size, offset);
1890
1891     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1892     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1893
1894   }
1895   PCOR(pcop)->instance = offset;
1896
1897   return pcop;
1898 }
1899
1900 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1901 {
1902   pCodeOp *pcop;
1903
1904 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1905
1906         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1907         PCOR(pcop)->rIdx = rIdx;
1908         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1909
1910         PCOR(pcop)->r->isFree = 0;
1911         PCOR(pcop)->r->wasUsed = 1;
1912
1913         pcop->type = PCOR(pcop)->r->pc_type;
1914
1915   return pcop;
1916 }
1917
1918 /*---------------------------------------------------------------------------------*/
1919 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1920 /*                 VR 030601                                                       */
1921 /*---------------------------------------------------------------------------------*/
1922 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1923 {
1924   pCodeOpReg2 *pcop2;
1925   pCodeOp *temp;
1926   
1927         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1928
1929         /* comment the following check, so errors to throw up */
1930 //      if(!pcop2)return NULL;
1931
1932         temp = pic16_popGet(aop_dst, offset);
1933         pcop2->pcop2 = temp;
1934         
1935   return PCOP(pcop2);
1936 }
1937
1938
1939
1940 /*--------------------------------------------------------------------------------.-*/
1941 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1942 /*                  VR 030601 , adapted by Hans Dorn                                */
1943 /*--------------------------------------------------------------------------------.-*/
1944 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1945 {
1946   pCodeOpReg2 *pcop2;
1947  
1948         pcop2 = (pCodeOpReg2 *)src;
1949         pcop2->pcop2 = dst;
1950         
1951         return PCOP(pcop2);
1952 }
1953
1954
1955
1956 /*---------------------------------------------------------------------------------*/
1957 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1958 /*                     movff instruction                                           */
1959 /*---------------------------------------------------------------------------------*/
1960 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1961 {
1962   pCodeOpReg2 *pcop2;
1963
1964         if(!noalloc) {
1965                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1966                 pcop2->pcop2 = pic16_popCopyReg(dst);
1967         } else {
1968                 /* the pCodeOp may be already allocated */
1969                 pcop2 = (pCodeOpReg2 *)(src);
1970                 pcop2->pcop2 = (pCodeOp *)(dst);
1971         }
1972
1973   return PCOP(pcop2);
1974 }
1975
1976
1977 /*-----------------------------------------------------------------*/
1978 /* pic16_popGet - asm operator to pcode operator conversion              */
1979 /*-----------------------------------------------------------------*/
1980 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1981 {
1982   //char *s = buffer ;
1983   char *rs;
1984   pCodeOp *pcop;
1985
1986     FENTRY2;
1987     /* offset is greater than
1988     size then zero */
1989
1990 //    if (offset > (aop->size - 1) &&
1991 //        aop->type != AOP_LIT)
1992 //      return NULL;  //zero;
1993
1994     /* depending on type */
1995     switch (aop->type) {
1996         
1997     case AOP_R0:
1998     case AOP_R1:
1999     case AOP_DPTR:
2000     case AOP_DPTR2:
2001         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2002         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2003         assert( 0 );
2004         return NULL;
2005
2006
2007     case AOP_FSR0:
2008     case AOP_FSR2:
2009       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2010       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
2011       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2012       PCOR(pcop)->r->wasUsed = 1;
2013       PCOR(pcop)->r->isFree = 0;
2014       
2015       PCOR(pcop)->instance = offset;
2016       pcop->type = PCOR(pcop)->r->pc_type;
2017       return (pcop);
2018
2019     case AOP_IMMD:
2020       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2021       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2022
2023     case AOP_STA:
2024       /* pCodeOp is already allocated from aopForSym */
2025         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2026         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2027           
2028       return (pcop);
2029       
2030     case AOP_ACC:
2031       {
2032         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
2033
2034         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2035
2036         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2037         
2038         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2039         PCOR(pcop)->rIdx = rIdx;
2040         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2041         PCOR(pcop)->r->wasUsed=1;
2042         PCOR(pcop)->r->isFree=0;
2043
2044         PCOR(pcop)->instance = offset;
2045         pcop->type = PCOR(pcop)->r->pc_type;
2046 //      rs = aop->aopu.aop_reg[offset]->name;
2047 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2048         return pcop;
2049
2050
2051 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2052 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2053
2054 //      assert( 0 );
2055       }
2056         
2057     case AOP_DIR:
2058       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2059       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2060         
2061 #if 0
2062     case AOP_PAGED:
2063       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2064       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2065 #endif
2066
2067     case AOP_REG:
2068       {
2069         int rIdx;
2070         assert (aop && aop->aopu.aop_reg[offset] != NULL);
2071         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2072
2073         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2074         
2075         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2076 //      pcop->type = PO_GPR_REGISTER;
2077         PCOR(pcop)->rIdx = rIdx;
2078         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
2079         PCOR(pcop)->r->wasUsed=1;
2080         PCOR(pcop)->r->isFree=0;
2081
2082         PCOR(pcop)->instance = offset;
2083         pcop->type = PCOR(pcop)->r->pc_type;
2084         
2085         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2086         rs = aop->aopu.aop_reg[offset]->name;
2087         DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2088         return pcop;
2089       }
2090
2091     case AOP_CRY:
2092         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2093
2094       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2095       PCOR(pcop)->instance = offset;
2096       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2097       //if(PCOR(pcop)->r == NULL)
2098       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2099       return pcop;
2100         
2101     case AOP_LIT:
2102         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2103       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2104
2105     case AOP_STR:
2106       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2107       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2108
2109       /*
2110       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2111       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2112       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2113       pcop->type = PCOR(pcop)->r->pc_type;
2114       pcop->name = PCOR(pcop)->r->name;
2115
2116       return pcop;
2117       */
2118
2119     case AOP_PCODE:
2120       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2121                           __LINE__, 
2122                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2123       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2124       switch( aop->aopu.pcop->type ) {
2125         case PO_DIR: PCOR(pcop)->instance += offset; break;
2126         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2127         case PO_WREG:
2128             assert (offset==0);
2129             break;
2130         default:
2131           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2132           assert( 0 );  /* should never reach here */;
2133       }
2134       return pcop;
2135     }
2136
2137     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2138            "pic16_popGet got unsupported aop->type");
2139     exit(0);
2140 }
2141 /*-----------------------------------------------------------------*/
2142 /* pic16_aopPut - puts a string for a aop                                */
2143 /*-----------------------------------------------------------------*/
2144 void pic16_aopPut (asmop *aop, char *s, int offset)
2145 {
2146     char *d = buffer ;
2147     symbol *lbl ;
2148
2149     return;
2150
2151     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2152
2153     if (aop->size && offset > ( aop->size - 1)) {
2154         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2155                "pic16_aopPut got offset > aop->size");
2156         exit(0);
2157     }
2158
2159     /* will assign value to value */
2160     /* depending on where it is ofcourse */
2161     switch (aop->type) {
2162     case AOP_DIR:
2163       if (offset) {
2164         sprintf(d,"(%s + %d)",
2165                 aop->aopu.aop_dir,offset);
2166         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2167
2168       } else
2169             sprintf(d,"%s",aop->aopu.aop_dir);
2170         
2171         if (strcmp(d,s)) {
2172           DEBUGpic16_emitcode(";","%d",__LINE__);
2173           if(strcmp(s,"W"))
2174             pic16_emitcode("movf","%s,w",s);
2175           pic16_emitcode("movwf","%s",d);
2176
2177           if(strcmp(s,"W")) {
2178             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2179             if(offset >= aop->size) {
2180               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2181               break;
2182             } else
2183               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2184           }
2185
2186           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2187
2188
2189         }
2190         break;
2191         
2192     case AOP_REG:
2193       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2194         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2195           /*
2196             if (*s == '@'           ||
2197                 strcmp(s,"r0") == 0 ||
2198                 strcmp(s,"r1") == 0 ||
2199                 strcmp(s,"r2") == 0 ||
2200                 strcmp(s,"r3") == 0 ||
2201                 strcmp(s,"r4") == 0 ||
2202                 strcmp(s,"r5") == 0 ||
2203                 strcmp(s,"r6") == 0 || 
2204                 strcmp(s,"r7") == 0 )
2205                 pic16_emitcode("mov","%s,%s  ; %d",
2206                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2207             else
2208           */
2209
2210           if(strcmp(s,"W")==0 )
2211             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2212
2213           pic16_emitcode("movwf","%s",
2214                    aop->aopu.aop_reg[offset]->name);
2215
2216           if(strcmp(s,zero)==0) {
2217             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2218
2219           } else if(strcmp(s,"W")==0) {
2220             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2221             pcop->type = PO_GPR_REGISTER;
2222
2223             PCOR(pcop)->rIdx = -1;
2224             PCOR(pcop)->r = NULL;
2225
2226             DEBUGpic16_emitcode(";","%d",__LINE__);
2227             pcop->name = Safe_strdup(s);
2228             pic16_emitpcode(POC_MOVFW,pcop);
2229             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2230           } else if(strcmp(s,one)==0) {
2231             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2232             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2233           } else {
2234             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2235           }
2236         }
2237         break;
2238         
2239     case AOP_DPTR:
2240     case AOP_DPTR2:
2241     
2242     if (aop->type == AOP_DPTR2)
2243     {
2244         genSetDPTR(1);
2245     }
2246     
2247         if (aop->code) {
2248             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2249                    "pic16_aopPut writting to code space");
2250             exit(0);
2251         }
2252         
2253         while (offset > aop->coff) {
2254             aop->coff++;
2255             pic16_emitcode ("inc","dptr");
2256         }
2257         
2258         while (offset < aop->coff) {
2259             aop->coff-- ;
2260             pic16_emitcode("lcall","__decdptr");
2261         }
2262         
2263         aop->coff = offset;
2264         
2265         /* if not in accumulater */
2266         MOVA(s);        
2267         
2268         pic16_emitcode ("movx","@dptr,a");
2269         
2270     if (aop->type == AOP_DPTR2)
2271     {
2272         genSetDPTR(0);
2273     }
2274         break;
2275         
2276     case AOP_R0:
2277     case AOP_R1:
2278         while (offset > aop->coff) {
2279             aop->coff++;
2280             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2281         }
2282         while (offset < aop->coff) {
2283             aop->coff-- ;
2284             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2285         }
2286         aop->coff = offset;
2287         
2288         if (aop->paged) {
2289             MOVA(s);           
2290             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2291             
2292         } else
2293             if (*s == '@') {
2294                 MOVA(s);
2295                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2296             } else
2297                 if (strcmp(s,"r0") == 0 ||
2298                     strcmp(s,"r1") == 0 ||
2299                     strcmp(s,"r2") == 0 ||
2300                     strcmp(s,"r3") == 0 ||
2301                     strcmp(s,"r4") == 0 ||
2302                     strcmp(s,"r5") == 0 ||
2303                     strcmp(s,"r6") == 0 || 
2304                     strcmp(s,"r7") == 0 ) {
2305                     char buffer[10];
2306                     sprintf(buffer,"a%s",s);
2307                     pic16_emitcode("mov","@%s,%s",
2308                              aop->aopu.aop_ptr->name,buffer);
2309                 } else
2310                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2311         
2312         break;
2313         
2314     case AOP_STK:
2315         if (strcmp(s,"a") == 0)
2316             pic16_emitcode("push","acc");
2317         else
2318             pic16_emitcode("push","%s",s);
2319         
2320         break;
2321         
2322     case AOP_CRY:
2323         /* if bit variable */
2324         if (!aop->aopu.aop_dir) {
2325             pic16_emitcode("clr","a");
2326             pic16_emitcode("rlc","a");
2327         } else {
2328             if (s == zero) 
2329                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2330             else
2331                 if (s == one)
2332                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2333                 else
2334                     if (!strcmp(s,"c"))
2335                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2336                     else {
2337                         lbl = newiTempLabel(NULL);
2338                         
2339                         if (strcmp(s,"a")) {
2340                             MOVA(s);
2341                         }
2342                         pic16_emitcode("clr","c");
2343                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2344                         pic16_emitcode("cpl","c");
2345                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2346                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2347                     }
2348         }
2349         break;
2350         
2351     case AOP_STR:
2352         aop->coff = offset;
2353         if (strcmp(aop->aopu.aop_str[offset],s))
2354             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2355         break;
2356         
2357     case AOP_ACC:
2358         aop->coff = offset;
2359         if (!offset && (strcmp(s,"acc") == 0))
2360             break;
2361         
2362         if (strcmp(aop->aopu.aop_str[offset],s))
2363             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2364         break;
2365
2366     default :
2367         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2368 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2369 //             "pic16_aopPut got unsupported aop->type");
2370 //      exit(0);    
2371     }    
2372
2373 }
2374
2375 /*-----------------------------------------------------------------*/
2376 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2377 /*-----------------------------------------------------------------*/
2378 void pic16_mov2w (asmop *aop, int offset)
2379 {
2380   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2381
2382   if(is_LitAOp(aop))
2383     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2384   else
2385     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2386 }
2387
2388 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2389 {
2390   if(is_LitAOp(src)) {
2391     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2392     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2393   } else {
2394     if(pic16_sameRegsOfs(src, dst, offset))return;
2395     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2396                       pic16_popGet(dst, offset)));
2397   }
2398 }
2399
2400 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2401 {
2402   if(is_LitAOp(src)) {
2403     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2404     pic16_emitpcode(POC_MOVWF, dst);
2405   } else {
2406     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2407   }
2408 }
2409
2410 void pic16_testStackOverflow(void)
2411 {
2412 #define GSTACK_TEST_NAME        "_gstack_test"
2413
2414   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2415   
2416   {
2417     symbol *sym;
2418
2419       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2420       sprintf(sym->rname, "%s%s", port->fun_prefix, GSTACK_TEST_NAME);
2421 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2422       checkAddSym(&externs, sym);
2423   }
2424
2425 }
2426
2427 /* push pcop into stack */
2428 void pic16_pushpCodeOp(pCodeOp *pcop)
2429 {
2430 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2431   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));    //&pic16_pc_postdec1)));
2432   if(pic16_options.gstack)
2433     pic16_testStackOverflow();
2434     
2435 }
2436
2437 /* pop pcop from stack */
2438 void pic16_poppCodeOp(pCodeOp *pcop)
2439 {
2440   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2441   if(pic16_options.gstack)
2442     pic16_testStackOverflow();
2443 }
2444
2445
2446 /*-----------------------------------------------------------------*/
2447 /* pushw - pushes wreg to stack                                    */
2448 /*-----------------------------------------------------------------*/
2449 void pushw(void)
2450 {
2451   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2452   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2453   if(pic16_options.gstack)
2454     pic16_testStackOverflow();
2455 }
2456
2457                 
2458 /*-----------------------------------------------------------------*/
2459 /* pushaop - pushes aop to stack                                   */
2460 /*-----------------------------------------------------------------*/
2461 void pushaop(asmop *aop, int offset)
2462 {
2463   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2464
2465   if(is_LitAOp(aop)) {
2466     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2467     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2468   } else {
2469     pic16_emitpcode(POC_MOVFF,
2470       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2471   }
2472
2473   if(pic16_options.gstack)
2474     pic16_testStackOverflow();
2475 }
2476
2477 /*-----------------------------------------------------------------*/
2478 /* popaop - pops aop from stack                                    */
2479 /*-----------------------------------------------------------------*/
2480 void popaop(asmop *aop, int offset)
2481 {
2482   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2483   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2484   if(pic16_options.gstack)
2485     pic16_testStackOverflow();
2486 }
2487
2488 void popaopidx(asmop *aop, int offset, int index)
2489 {
2490   int ofs=1;
2491
2492     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2493
2494     if(STACK_MODEL_LARGE)ofs++;
2495
2496     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2497     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2498     if(pic16_options.gstack)
2499       pic16_testStackOverflow();
2500 }
2501
2502 #if !(USE_GENERIC_SIGNED_SHIFT)
2503 /*-----------------------------------------------------------------*/
2504 /* reAdjustPreg - points a register back to where it should        */
2505 /*-----------------------------------------------------------------*/
2506 static void reAdjustPreg (asmop *aop)
2507 {
2508     int size ;
2509
2510     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2511     aop->coff = 0;
2512     if ((size = aop->size) <= 1)
2513         return ;
2514     size-- ;
2515     switch (aop->type) {
2516         case AOP_R0 :
2517         case AOP_R1 :
2518             while (size--)
2519                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2520             break;          
2521         case AOP_DPTR :
2522         case AOP_DPTR2:
2523             if (aop->type == AOP_DPTR2)
2524             {
2525                 genSetDPTR(1);
2526             } 
2527             while (size--)
2528             {
2529                 pic16_emitcode("lcall","__decdptr");
2530             }
2531                 
2532             if (aop->type == AOP_DPTR2)
2533             {
2534                 genSetDPTR(0);
2535             }                
2536             break;  
2537
2538     }   
2539
2540 }
2541 #endif
2542
2543 #if 0
2544 /*-----------------------------------------------------------------*/
2545 /* opIsGptr: returns non-zero if the passed operand is             */   
2546 /* a generic pointer type.                                         */
2547 /*-----------------------------------------------------------------*/ 
2548 static int opIsGptr(operand *op)
2549 {
2550     sym_link *type = operandType(op);
2551     
2552     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2553     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2554     {
2555         return 1;
2556     }
2557     return 0;        
2558 }
2559 #endif
2560
2561 /*-----------------------------------------------------------------*/
2562 /* pic16_getDataSize - get the operand data size                         */
2563 /*-----------------------------------------------------------------*/
2564 int pic16_getDataSize(operand *op)
2565 {
2566     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2567
2568
2569     return AOP_SIZE(op);
2570
2571     // tsd- in the pic port, the genptr size is 1, so this code here
2572     // fails. ( in the 8051 port, the size was 4).
2573 #if 0
2574     int size;
2575     size = AOP_SIZE(op);
2576     if (size == GPTRSIZE)
2577     {
2578         sym_link *type = operandType(op);
2579         if (IS_GENPTR(type))
2580         {
2581             /* generic pointer; arithmetic operations
2582              * should ignore the high byte (pointer type).
2583              */
2584             size--;
2585     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2586         }
2587     }
2588     return size;
2589 #endif
2590 }
2591
2592 /*-----------------------------------------------------------------*/
2593 /* pic16_outAcc - output Acc                                             */
2594 /*-----------------------------------------------------------------*/
2595 void pic16_outAcc(operand *result)
2596 {
2597   int size,offset;
2598   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2599   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2600
2601
2602   size = pic16_getDataSize(result);
2603   if(size){
2604     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2605     size--;
2606     offset = 1;
2607     /* unsigned or positive */
2608     while(size--)
2609       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2610   }
2611
2612 }
2613
2614 /*-----------------------------------------------------------------*/
2615 /* pic16_outBitC - output a bit C                                  */
2616 /*                 Move to result the value of Carry flag -- VR    */
2617 /*-----------------------------------------------------------------*/
2618 void pic16_outBitC(operand *result)
2619 {
2620   int i;
2621
2622     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2623
2624     /* if the result is bit */
2625     if (AOP_TYPE(result) == AOP_CRY) {
2626         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2627         pic16_aopPut(AOP(result),"c",0);
2628     } else {
2629
2630         i = AOP_SIZE(result);
2631         while(i--) {
2632                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2633         }
2634         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2635     }
2636 }
2637
2638 /*-----------------------------------------------------------------*/
2639 /* pic16_outBitOp - output a bit from Op                           */
2640 /*                 Move to result the value of set/clr op -- VR    */
2641 /*-----------------------------------------------------------------*/
2642 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2643 {
2644   int i;
2645
2646     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2647
2648     /* if the result is bit */
2649     if (AOP_TYPE(result) == AOP_CRY) {
2650         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2651         pic16_aopPut(AOP(result),"c",0);
2652     } else {
2653
2654         i = AOP_SIZE(result);
2655         while(i--) {
2656                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2657         }
2658         pic16_emitpcode(POC_RRCF, pcop);          
2659         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2660     }
2661 }
2662
2663 /*-----------------------------------------------------------------*/
2664 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2665 /*-----------------------------------------------------------------*/
2666 void pic16_toBoolean(operand *oper)
2667 {
2668     int size = AOP_SIZE(oper) - 1;
2669     int offset = 1;
2670
2671     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2672
2673     if ( AOP_TYPE(oper) != AOP_ACC) {
2674       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2675     }
2676     while (size--) {
2677       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2678     }
2679 }
2680
2681
2682 #if !defined(GEN_Not)
2683 /*-----------------------------------------------------------------*/
2684 /* genNot - generate code for ! operation                          */
2685 /*-----------------------------------------------------------------*/
2686 static void pic16_genNot (iCode *ic)
2687 {
2688   symbol *tlbl;
2689   int size;
2690
2691   FENTRY;
2692   /* assign asmOps to operand & result */
2693   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2694   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2695
2696   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2697   /* if in bit space then a special case */
2698   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2699     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2700       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2701       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2702     } else {
2703       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2704       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2705       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2706     }
2707     goto release;
2708   }
2709
2710   size = AOP_SIZE(IC_LEFT(ic));
2711   if(size == 1) {
2712     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2713     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2714     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2715     goto release;
2716   }
2717   pic16_toBoolean(IC_LEFT(ic));
2718
2719   tlbl = newiTempLabel(NULL);
2720   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2721   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2722   pic16_outBitC(IC_RESULT(ic));
2723
2724  release:    
2725   /* release the aops */
2726   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2727   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2728 }
2729 #endif
2730
2731
2732 #if !defined(GEN_Cpl)
2733 /*-----------------------------------------------------------------*/
2734 /* genCpl - generate code for complement                           */
2735 /*-----------------------------------------------------------------*/
2736 static void pic16_genCpl (iCode *ic)
2737 {
2738   int offset = 0;
2739   int size ;
2740
2741     FENTRY;
2742     /* assign asmOps to operand & result */
2743     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2744     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2745
2746     /* if both are in bit space then 
2747     a special case */
2748     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2749         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2750
2751         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2752         pic16_emitcode("cpl","c"); 
2753         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2754         goto release; 
2755     } 
2756
2757     size = AOP_SIZE(IC_RESULT(ic));
2758     while (size--) {
2759 /*
2760         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2761         MOVA(l);       
2762         pic16_emitcode("cpl","a");
2763         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2764 */
2765         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2766               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2767         } else {
2768                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2769                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2770         }
2771         offset++;
2772
2773     }
2774
2775
2776 release:
2777     /* release the aops */
2778     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2779     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2780 }
2781 #endif
2782
2783 /*-----------------------------------------------------------------*/
2784 /* genUminusFloat - unary minus for floating points                */
2785 /*-----------------------------------------------------------------*/
2786 static void genUminusFloat(operand *op,operand *result)
2787 {
2788   int size ,offset =0 ;
2789   
2790     FENTRY;
2791     /* for this we just need to flip the 
2792     first it then copy the rest in place */
2793     size = AOP_SIZE(op);
2794
2795     while(size--) {
2796       pic16_mov2f(AOP(result), AOP(op), offset);
2797       offset++;
2798     }
2799     
2800     /* toggle the MSB's highest bit */
2801     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2802 }
2803
2804 /*-----------------------------------------------------------------*/
2805 /* genUminus - unary minus code generation                         */
2806 /*-----------------------------------------------------------------*/
2807 static void genUminus (iCode *ic)
2808 {
2809   int size, i;
2810   sym_link *optype, *rtype;
2811   symbol *label;
2812   int needLabel=0;
2813
2814     FENTRY;     
2815     
2816     /* assign asmops */
2817     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2818     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2819
2820     /* if both in bit space then special case */
2821     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2822       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2823         
2824         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2825         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2826         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2827         goto release; 
2828     } 
2829
2830     optype = operandType(IC_LEFT(ic));
2831     rtype = operandType(IC_RESULT(ic));
2832
2833
2834     /* if float then do float stuff */
2835     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2836       if(IS_FIXED(optype))
2837         debugf("implement fixed16x16 type\n", 0);
2838         
2839         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2840         goto release;
2841     }
2842
2843     /* otherwise subtract from zero by taking the 2's complement */
2844     size = AOP_SIZE(IC_LEFT(ic));
2845     label = newiTempLabel ( NULL );
2846     
2847     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2848       for (i=size-1; i > 0; i--) {
2849         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2850       } // for
2851       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2852       for (i=1; i < size; i++) {
2853         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2854         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2855       } // for
2856     } else {
2857       for (i=size-1; i >= 0; i--) {
2858         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2859         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2860       } // for
2861       if (size > 1) {
2862         for (i=0; i < size-2; i++) {
2863           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2864           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2865         } // for
2866         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2867       } // if
2868       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2869     }
2870     if (needLabel)
2871       pic16_emitpLabel (label->key);
2872
2873 release:
2874     /* release the aops */
2875     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2876     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2877 }
2878
2879 #if 0
2880 /*-----------------------------------------------------------------*/
2881 /* saveRegisters - will look for a call and save the registers     */
2882 /*-----------------------------------------------------------------*/
2883 static void saveRegisters(iCode *lic) 
2884 {
2885     int i;
2886     iCode *ic;
2887     bitVect *rsave;
2888     sym_link *dtype;
2889
2890     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2891     /* look for call */
2892     for (ic = lic ; ic ; ic = ic->next) 
2893         if (ic->op == CALL || ic->op == PCALL)
2894             break;
2895
2896     if (!ic) {
2897         fprintf(stderr,"found parameter push with no function call\n");
2898         return ;
2899     }
2900
2901     /* if the registers have been saved already then
2902     do nothing */
2903     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2904         return ;
2905
2906     /* find the registers in use at this time 
2907     and push them away to safety */
2908     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2909                           ic->rUsed);
2910
2911     ic->regsSaved = 1;
2912     if (options.useXstack) {
2913         if (bitVectBitValue(rsave,R0_IDX))
2914             pic16_emitcode("mov","b,r0");
2915         pic16_emitcode("mov","r0,%s",spname);
2916         for (i = 0 ; i < pic16_nRegs ; i++) {
2917             if (bitVectBitValue(rsave,i)) {
2918                 if (i == R0_IDX)
2919                     pic16_emitcode("mov","a,b");
2920                 else
2921                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2922                 pic16_emitcode("movx","@r0,a");
2923                 pic16_emitcode("inc","r0");
2924             }
2925         }
2926         pic16_emitcode("mov","%s,r0",spname);
2927         if (bitVectBitValue(rsave,R0_IDX))
2928             pic16_emitcode("mov","r0,b");           
2929     }// else
2930     //for (i = 0 ; i < pic16_nRegs ; i++) {
2931     //    if (bitVectBitValue(rsave,i))
2932     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2933     //}
2934
2935     dtype = operandType(IC_LEFT(ic));
2936     if (currFunc && dtype && 
2937         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2938         IFFUNC_ISISR(currFunc->type) &&
2939         !ic->bankSaved) 
2940
2941         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2942
2943 }
2944 /*-----------------------------------------------------------------*/
2945 /* unsaveRegisters - pop the pushed registers                      */
2946 /*-----------------------------------------------------------------*/
2947 static void unsaveRegisters (iCode *ic)
2948 {
2949     int i;
2950     bitVect *rsave;
2951
2952     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2953     /* find the registers in use at this time 
2954     and push them away to safety */
2955     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2956                           ic->rUsed);
2957     
2958     if (options.useXstack) {
2959         pic16_emitcode("mov","r0,%s",spname);   
2960         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2961             if (bitVectBitValue(rsave,i)) {
2962                 pic16_emitcode("dec","r0");
2963                 pic16_emitcode("movx","a,@r0");
2964                 if (i == R0_IDX)
2965                     pic16_emitcode("mov","b,a");
2966                 else
2967                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2968             }       
2969
2970         }
2971         pic16_emitcode("mov","%s,r0",spname);
2972         if (bitVectBitValue(rsave,R0_IDX))
2973             pic16_emitcode("mov","r0,b");
2974     } //else
2975     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2976     //    if (bitVectBitValue(rsave,i))
2977     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2978     //}
2979
2980 }  
2981 #endif
2982
2983 #if 0  // patch 14
2984 /*-----------------------------------------------------------------*/
2985 /* pushSide -                                                      */
2986 /*-----------------------------------------------------------------*/
2987 static void pushSide(operand * oper, int size)
2988 {
2989         int offset = 0;
2990     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2991         while (size--) {
2992                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2993                 if (AOP_TYPE(oper) != AOP_REG &&
2994                     AOP_TYPE(oper) != AOP_DIR &&
2995                     strcmp(l,"a") ) {
2996                         pic16_emitcode("mov","a,%s",l);
2997                         pic16_emitcode("push","acc");
2998                 } else
2999                         pic16_emitcode("push","%s",l);
3000         }
3001 }
3002 #endif // patch 14
3003
3004 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
3005 {
3006   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
3007     pic16_emitpcode(POC_MOVFW, src);
3008     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
3009   } else {
3010     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3011         src, pic16_popGet(AOP(op), offset)));
3012   }
3013 }
3014
3015
3016 /*-----------------------------------------------------------------*/
3017 /* assignResultValue - assign results to oper, rescall==1 is       */
3018 /*                     called from genCall() or genPcall()         */
3019 /*-----------------------------------------------------------------*/
3020 static void assignResultValue(operand * oper, int rescall)
3021 {
3022   int size = AOP_SIZE(oper);
3023   int offset=0;
3024   
3025     FENTRY2;
3026 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3027     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3028
3029     if(rescall) {
3030       /* assign result from a call/pcall function() */
3031                 
3032       /* function results are stored in a special order,
3033        * see top of file with Function return policy, or manual */
3034
3035       if(size <= 4) {
3036         /* 8-bits, result in WREG */
3037         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3038                         
3039         if(size>1) {
3040           /* 16-bits, result in PRODL:WREG */
3041           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3042         }
3043                         
3044         if(size>2) {
3045           /* 24-bits, result in PRODH:PRODL:WREG */
3046           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3047         }
3048                         
3049         if(size>3) {
3050           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3051           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3052         }
3053       
3054       } else {
3055         /* >32-bits, result on stack, and FSR0 points to beginning.
3056          * Fix stack when done */
3057         /* FIXME FIXME */
3058 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3059         while (size--) {
3060 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3061 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3062                 
3063           popaopidx(AOP(oper), size, GpsuedoStkPtr);
3064           GpsuedoStkPtr++;
3065         }
3066                         
3067         /* fix stack */
3068         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3069         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3070         if(STACK_MODEL_LARGE) {
3071           emitSKPNC;
3072           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3073         }
3074       }                 
3075     } else {
3076       int areg = 0;             /* matching argument register */
3077       
3078 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3079       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3080
3081
3082       /* its called from genReceive (probably) -- VR */
3083       /* I hope this code will not be called from somewhere else in the future! 
3084        * We manually set the pseudo stack pointer in genReceive. - dw
3085        */
3086       if(!GpsuedoStkPtr && _G.useWreg) {
3087 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3088
3089         /* The last byte in the assignment is in W */
3090         if(areg <= GpsuedoStkPtr) {
3091           size--;
3092           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3093           offset++;
3094 //          debugf("receive from WREG\n", 0);
3095         }
3096         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3097       }
3098 //      GpsuedoStkPtr++;
3099       _G.stack_lat = AOP_SIZE(oper)-1;
3100
3101       while (size) {
3102         size--;
3103         GpsuedoStkPtr++;
3104         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3105 //        debugf("receive from STACK\n", 0);
3106         offset++;
3107       }
3108     }
3109 }
3110
3111
3112 /*-----------------------------------------------------------------*/
3113 /* genIpush - generate code for pushing this gets a little complex */
3114 /*-----------------------------------------------------------------*/
3115 static void genIpush (iCode *ic)
3116 {
3117 //  int size, offset=0;
3118
3119   FENTRY;
3120   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3121
3122   if(ic->parmPush) {
3123     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3124
3125     /* send to stack as normal */
3126     addSet(&_G.sendSet,ic);
3127 //    addSetHead(&_G.sendSet,ic);
3128     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3129   }
3130
3131         
3132 #if 0
3133     int size, offset = 0 ;
3134     char *l;
3135
3136
3137     /* if this is not a parm push : ie. it is spill push 
3138     and spill push is always done on the local stack */
3139     if (!ic->parmPush) {
3140
3141         /* and the item is spilt then do nothing */
3142         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3143             return ;
3144
3145         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3146         size = AOP_SIZE(IC_LEFT(ic));
3147         /* push it on the stack */
3148         while(size--) {
3149             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3150             if (*l == '#') {
3151                 MOVA(l);
3152                 l = "acc";
3153             }
3154             pic16_emitcode("push","%s",l);
3155         }
3156         return ;        
3157     }
3158
3159     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3160 #endif
3161 }
3162
3163 /*-----------------------------------------------------------------*/
3164 /* genIpop - recover the registers: can happen only for spilling   */
3165 /*-----------------------------------------------------------------*/
3166 static void genIpop (iCode *ic)
3167 {
3168   FENTRY;
3169   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3170 #if 0
3171     int size,offset ;
3172
3173
3174     /* if the temp was not pushed then */
3175     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3176         return ;
3177
3178     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3179     size = AOP_SIZE(IC_LEFT(ic));
3180     offset = (size-1);
3181     while (size--) 
3182         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3183                                    FALSE,TRUE));
3184
3185     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3186 #endif
3187 }
3188
3189 #if 0
3190 /*-----------------------------------------------------------------*/
3191 /* unsaverbank - restores the resgister bank from stack            */
3192 /*-----------------------------------------------------------------*/
3193 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3194 {
3195   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3196 #if 0
3197     int i;
3198     asmop *aop ;
3199     regs *r = NULL;
3200
3201     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3202     if (popPsw) {
3203         if (options.useXstack) {
3204             aop = newAsmop(0);
3205             r = getFreePtr(ic,&aop,FALSE);
3206             
3207             
3208             pic16_emitcode("mov","%s,_spx",r->name);
3209             pic16_emitcode("movx","a,@%s",r->name);
3210             pic16_emitcode("mov","psw,a");
3211             pic16_emitcode("dec","%s",r->name);
3212             
3213         }else
3214             pic16_emitcode ("pop","psw");
3215     }
3216
3217     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3218         if (options.useXstack) {       
3219             pic16_emitcode("movx","a,@%s",r->name);
3220             //pic16_emitcode("mov","(%s+%d),a",
3221             //       regspic16[i].base,8*bank+regspic16[i].offset);
3222             pic16_emitcode("dec","%s",r->name);
3223
3224         } else 
3225           pic16_emitcode("pop",""); //"(%s+%d)",
3226         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3227     }
3228
3229     if (options.useXstack) {
3230
3231         pic16_emitcode("mov","_spx,%s",r->name);
3232         pic16_freeAsmop(NULL,aop,ic,TRUE);
3233
3234     }
3235 #endif 
3236 }
3237
3238 /*-----------------------------------------------------------------*/
3239 /* saverbank - saves an entire register bank on the stack          */
3240 /*-----------------------------------------------------------------*/
3241 static void saverbank (int bank, iCode *ic, bool pushPsw)
3242 {
3243   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3244 #if 0
3245     int i;
3246     asmop *aop ;
3247     regs *r = NULL;
3248
3249     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3250     if (options.useXstack) {
3251
3252         aop = newAsmop(0);
3253         r = getFreePtr(ic,&aop,FALSE);  
3254         pic16_emitcode("mov","%s,_spx",r->name);
3255
3256     }
3257
3258     for (i = 0 ; i < pic16_nRegs ;i++) {
3259         if (options.useXstack) {
3260             pic16_emitcode("inc","%s",r->name);
3261             //pic16_emitcode("mov","a,(%s+%d)",
3262             //         regspic16[i].base,8*bank+regspic16[i].offset);
3263             pic16_emitcode("movx","@%s,a",r->name);           
3264         } else 
3265           pic16_emitcode("push","");// "(%s+%d)",
3266                      //regspic16[i].base,8*bank+regspic16[i].offset);
3267     }
3268     
3269     if (pushPsw) {
3270         if (options.useXstack) {
3271             pic16_emitcode("mov","a,psw");
3272             pic16_emitcode("movx","@%s,a",r->name);     
3273             pic16_emitcode("inc","%s",r->name);
3274             pic16_emitcode("mov","_spx,%s",r->name);       
3275             pic16_freeAsmop (NULL,aop,ic,TRUE);
3276             
3277         } else
3278             pic16_emitcode("push","psw");
3279         
3280         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3281     }
3282     ic->bankSaved = 1;
3283 #endif
3284 }
3285 #endif  /* 0 */
3286
3287
3288 static int wparamCmp(void *p1, void *p2)
3289 {
3290   return (!strcmp((char *)p1, (char *)p2));
3291 }
3292
3293 int inWparamList(char *s)
3294 {
3295   return isinSetWith(wparamList, s, wparamCmp);
3296
3297
3298
3299 /*-----------------------------------------------------------------*/
3300 /* genCall - generates a call statement                            */
3301 /*-----------------------------------------------------------------*/
3302 static void genCall (iCode *ic)
3303 {
3304   sym_link *ftype;   
3305   int stackParms=0;
3306   int use_wreg=0;
3307   int inwparam=0;
3308   char *fname;
3309   
3310     FENTRY;
3311
3312     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3313     /* if caller saves & we have not saved then */
3314 //    if (!ic->regsSaved)
3315 //      saveRegisters(ic);
3316
3317         /* initialise stackParms for IPUSH pushes */
3318 //      stackParms = psuedoStkPtr;
3319 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3320     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3321     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3322
3323 #if 0
3324     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3325 #endif
3326
3327     /* if send set is not empty the assign */
3328     if (_G.sendSet) {
3329       iCode *sic;
3330       int psuedoStkPtr=-1; 
3331       int firstTimeThruLoop = 1;
3332
3333
3334         /* reverse sendSet if function is not reentrant */
3335         if(!IFFUNC_ISREENT(ftype))
3336           _G.sendSet = reverseSet(_G.sendSet);
3337
3338         /* First figure how many parameters are getting passed */
3339         stackParms = 0;
3340         use_wreg = 0;
3341         
3342         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3343           int size;
3344 //          int offset = 0;
3345
3346             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3347             size = AOP_SIZE(IC_LEFT(sic));
3348
3349             stackParms += size;
3350
3351             /* pass the last byte through WREG */
3352             if(inwparam) {
3353
3354               while (size--) {
3355                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3356                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3357                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3358
3359                 if(!firstTimeThruLoop) {
3360                   /* If this is not the first time we've been through the loop
3361                    * then we need to save the parameter in a temporary
3362                    * register. The last byte of the last parameter is
3363                    * passed in W. */
3364
3365                   pushw();
3366 //                  --psuedoStkPtr;             // sanity check
3367                   use_wreg = 1;
3368                 }
3369                 
3370                 firstTimeThruLoop=0;
3371
3372                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3373
3374 //                offset++;
3375               }
3376             } else {
3377               /* all arguments are passed via stack */
3378               use_wreg = 0;
3379
3380               while (size--) {
3381                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3382                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3383                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3384
3385 //                pushaop(AOP(IC_LEFT(sic)), size);
3386                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3387
3388                 if(!_G.resDirect)
3389                   pushw();
3390               }
3391             }
3392
3393             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3394           }
3395
3396           if(inwparam) {
3397             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3398               pushw();  /* save last parameter to stack if functions has varargs */
3399               use_wreg = 0;
3400             } else
3401               use_wreg = 1;
3402           } else use_wreg = 0;
3403
3404           _G.stackRegSet = _G.sendSet;
3405           _G.sendSet = NULL;
3406     }
3407
3408     /* make the call */
3409     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3410
3411     GpsuedoStkPtr=0;
3412     
3413     /* if we need to assign a result value */
3414     if ((IS_ITEMP(IC_RESULT(ic))
3415           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3416               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3417         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3418
3419       _G.accInUse++;
3420       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3421       _G.accInUse--;
3422
3423       assignResultValue(IC_RESULT(ic), 1);
3424
3425       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3426                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3427                 
3428       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3429     }
3430
3431     if(!stackParms && ic->parmBytes) {
3432       stackParms = ic->parmBytes;
3433     }
3434       
3435     stackParms -= use_wreg;
3436     
3437     if(stackParms>0) {
3438       if(stackParms == 1) {
3439         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3440       } else {
3441         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3442         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3443       }
3444       if(STACK_MODEL_LARGE) {
3445         emitSKPNC;
3446         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3447       }
3448     }
3449
3450 #if 0
3451     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3452 #endif
3453
3454     /* adjust the stack for parameters if required */
3455 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3456
3457 #if 0
3458       /* if register bank was saved then pop them */
3459       if (ic->bankSaved)
3460         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3461
3462       /* if we hade saved some registers then unsave them */
3463       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3464         unsaveRegisters (ic);
3465 #endif
3466 }
3467
3468
3469
3470 /*-----------------------------------------------------------------*/
3471 /* genPcall - generates a call by pointer statement                */
3472 /*            new version, created from genCall - HJD              */
3473 /*-----------------------------------------------------------------*/
3474 static void genPcall (iCode *ic)
3475 {
3476   sym_link *ftype, *fntype;
3477   int stackParms=0;
3478   symbol *retlbl = newiTempLabel(NULL);
3479   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3480   
3481     FENTRY;
3482
3483     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3484     fntype = operandType( IC_LEFT(ic) )->next;
3485
3486     /* if send set is not empty the assign */
3487     if (_G.sendSet) {
3488       iCode *sic;
3489       int psuedoStkPtr=-1; 
3490
3491       /* reverse sendSet if function is not reentrant */
3492       if(!IFFUNC_ISREENT(fntype))
3493         _G.sendSet = reverseSet(_G.sendSet);
3494
3495       stackParms = 0;
3496       
3497       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3498         int size;
3499
3500           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3501           size = AOP_SIZE(IC_LEFT(sic));
3502           stackParms += size;
3503
3504           /* all parameters are passed via stack, since WREG is clobbered
3505            * by the calling sequence */
3506           while (size--) {
3507             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3508             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3509             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3510
3511             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3512             pushw();
3513           }
3514
3515           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3516       }
3517
3518       _G.stackRegSet = _G.sendSet;
3519       _G.sendSet = NULL;
3520     }
3521
3522     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3523
3524     // push return address
3525     // push $ on return stack, then replace with retlbl
3526
3527     /* Thanks to Thorsten Klose for pointing out that the following
3528      * snippet should be interrupt safe */
3529     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3530     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3531
3532     pic16_emitpcodeNULLop(POC_PUSH);
3533
3534     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3535     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3536     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3537     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3538     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3539     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3540
3541
3542     /* restore interrupt control register */
3543     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3544     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3545
3546     /* make the call by writing the pointer into pc */
3547     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3548     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3549
3550     // note: MOVFF to PCL not allowed
3551     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3552     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3553
3554
3555     /* return address is here: (X) */
3556     pic16_emitpLabelFORCE(retlbl->key);
3557
3558     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3559
3560     GpsuedoStkPtr=0;
3561     /* if we need assign a result value */
3562     if ((IS_ITEMP(IC_RESULT(ic))
3563           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3564               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3565         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3566
3567       _G.accInUse++;
3568       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3569       _G.accInUse--;
3570
3571       assignResultValue(IC_RESULT(ic), 1);
3572
3573       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3574               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3575                 
3576       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3577     }
3578
3579 //    stackParms -= use_wreg;
3580     
3581     if(stackParms>0) {
3582       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3583       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3584       if(STACK_MODEL_LARGE) {
3585         emitSKPNC;
3586         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3587       }
3588     }
3589 }
3590
3591 /*-----------------------------------------------------------------*/
3592 /* resultRemat - result  is rematerializable                       */
3593 /*-----------------------------------------------------------------*/
3594 static int resultRemat (iCode *ic)
3595 {
3596   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3597   if (SKIP_IC(ic) || ic->op == IFX)
3598     return 0;
3599
3600   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3601     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3602     if (sym->remat && !POINTER_SET(ic)) 
3603       return 1;
3604   }
3605
3606   return 0;
3607 }
3608
3609 #if defined(__BORLANDC__) || defined(_MSC_VER)
3610 #define STRCASECMP stricmp
3611 #else
3612 #define STRCASECMP strcasecmp
3613 #endif
3614
3615 #if 0
3616 /*-----------------------------------------------------------------*/
3617 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3618 /*-----------------------------------------------------------------*/
3619 static bool inExcludeList(char *s)
3620 {
3621   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3622     int i =0;
3623     
3624     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3625     if (options.excludeRegs[i] &&
3626     STRCASECMP(options.excludeRegs[i],"none") == 0)
3627         return FALSE ;
3628
3629     for ( i = 0 ; options.excludeRegs[i]; i++) {
3630         if (options.excludeRegs[i] &&
3631         STRCASECMP(s,options.excludeRegs[i]) == 0)
3632             return TRUE;
3633     }
3634     return FALSE ;
3635 }
3636 #endif
3637
3638 /*-----------------------------------------------------------------*/
3639 /* genFunction - generated code for function entry                 */
3640 /*-----------------------------------------------------------------*/
3641 static void genFunction (iCode *ic)
3642 {
3643   symbol *sym;
3644   sym_link *ftype;
3645   
3646     FENTRY;
3647     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3648
3649     pic16_labelOffset += (max_key+4);
3650     max_key=0;
3651     GpsuedoStkPtr=0;
3652     _G.nRegsSaved = 0;
3653         
3654     ftype = operandType(IC_LEFT(ic));
3655     sym = OP_SYMBOL(IC_LEFT(ic));
3656
3657     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3658       /* create an absolute section at the interrupt vector:
3659        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3660       symbol *asym;
3661       char asymname[128];
3662       pBlock *apb;
3663
3664 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3665
3666         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3667           sprintf(asymname, "ivec_%s", sym->name);
3668         else
3669           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3670   
3671         /* when an interrupt is declared as naked, do not emit the special
3672          * wrapper segment at vector address. The user should take care for
3673          * this instead. -- VR */
3674
3675         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3676           asym = newSymbol(asymname, 0);
3677           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3678           pic16_addpBlock( apb );
3679
3680           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3681           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3682           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3683           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3684           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3685                 
3686           /* mark the end of this tiny function */
3687           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3688         } else {
3689           sprintf(asymname, "%s", sym->rname);
3690         }
3691
3692         {
3693           absSym *abSym;
3694
3695             abSym = Safe_calloc(1, sizeof(absSym));
3696             strcpy(abSym->name, asymname);
3697
3698             switch( FUNC_INTNO(sym->type) ) {
3699               case 0: abSym->address = 0x000000; break;
3700               case 1: abSym->address = 0x000008; break;
3701               case 2: abSym->address = 0x000018; break;
3702               
3703               default:
3704 //                fprintf(stderr, "no interrupt number is given\n");
3705                 abSym->address = -1; break;
3706             }
3707
3708             /* relocate interrupt vectors if needed */
3709             if(abSym->address != -1)
3710               abSym->address += pic16_options.ivt_loc;
3711
3712             addSet(&absSymSet, abSym);
3713         }
3714     }
3715
3716     /* create the function header */
3717     pic16_emitcode(";","-----------------------------------------");
3718     pic16_emitcode(";"," function %s",sym->name);
3719     pic16_emitcode(";","-----------------------------------------");
3720
3721     pic16_emitcode("","%s:",sym->rname);
3722     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3723
3724     {
3725       absSym *ab;
3726
3727         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3728           if(!strcmp(ab->name, sym->rname)) {
3729             pic16_pBlockConvert2Absolute(pb);
3730             break;
3731           }
3732         }
3733     }
3734
3735     if(IFFUNC_ISNAKED(ftype)) {
3736       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3737       return;
3738     }
3739         
3740     /* if critical function then turn interrupts off */
3741     if (IFFUNC_ISCRITICAL(ftype)) {
3742       //pic16_emitcode("clr","ea");
3743     }
3744
3745     currFunc = sym;             /* update the currFunc symbol */
3746     _G.fregsUsed = sym->regsUsed;
3747     _G.sregsAlloc = newBitVect(128);
3748     
3749
3750     /* if this is an interrupt service routine then
3751      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3752     if (IFFUNC_ISISR(sym->type)) {
3753         _G.usefastretfie = 1;   /* use shadow registers by default */
3754         
3755         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3756         if(!FUNC_ISSHADOWREGS(sym->type)) {
3757           /* do not save WREG,STATUS,BSR for high priority interrupts
3758            * because they are stored in the hardware shadow registers already */
3759           _G.usefastretfie = 0;
3760           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3761           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3762           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3763         }
3764
3765         /* these should really be optimized somehow, because not all
3766          * interrupt handlers modify them */
3767         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3768         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3769         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3770         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3771         
3772 //        pic16_pBlockConvert2ISR(pb);
3773     }
3774
3775     /* emit code to setup stack frame if user enabled,
3776      * and function is not main() */
3777     
3778 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3779     if(strcmp(sym->name, "main")) {
3780       if(0 
3781         || !options.ommitFramePtr 
3782 //        || sym->regsUsed
3783         || IFFUNC_ARGS(sym->type)
3784         || FUNC_HASSTACKPARM(sym->etype)
3785         ) {
3786         /* setup the stack frame */
3787         if(STACK_MODEL_LARGE)
3788           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3789         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3790
3791         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3792         if(STACK_MODEL_LARGE)
3793           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3794       }
3795     }
3796
3797     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3798           && sym->stack) {
3799
3800       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3801
3802       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3803       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3804       emitSKPC;
3805       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3806     }
3807           
3808     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3809       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3810         _G.useWreg = 0;
3811       else
3812         _G.useWreg = 1;
3813     } else
3814       _G.useWreg = 0;
3815
3816     /* if callee-save to be used for this function
3817      * then save the registers being used in this function */
3818 //    if (IFFUNC_CALLEESAVES(sym->type))
3819     {
3820       int i;
3821
3822         /* if any registers used */
3823         if (sym->regsUsed) {
3824           /* save the registers used */
3825           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3826           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3827           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3828             if (bitVectBitValue(sym->regsUsed,i)) {
3829               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3830               _G.nRegsSaved++;
3831
3832               if(!pic16_regWithIdx(i)->wasUsed) {
3833                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3834                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3835                 pic16_regWithIdx(i)->wasUsed = 1;
3836               }
3837             }
3838           }
3839           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3840         }
3841     }
3842         
3843     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3844 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3845 }
3846
3847 /*-----------------------------------------------------------------*/
3848 /* genEndFunction - generates epilogue for functions               */
3849 /*-----------------------------------------------------------------*/
3850 static void genEndFunction (iCode *ic)
3851 {
3852   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3853
3854     FENTRY;
3855
3856     if(IFFUNC_ISNAKED(sym->type)) {
3857       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3858       return;
3859     }
3860
3861     _G.stack_lat = 0;
3862
3863     /* add code for ISCRITICAL */
3864     if(IFFUNC_ISCRITICAL(sym->type)) {
3865       /* if critical function, turn on interrupts */
3866       
3867       /* TODO: add code here -- VR */
3868     }
3869     
3870 //    sym->regsUsed = _G.fregsUsed;
3871     
3872     /* now we need to restore the registers */
3873     /* if any registers used */
3874
3875     /* first restore registers that might be used for stack access */
3876     if(_G.sregsAllocSet) {
3877     regs *sr;
3878     
3879       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3880       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3881         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3882       }
3883     }
3884
3885     if (sym->regsUsed) {
3886       int i;
3887
3888         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3889         /* restore registers used */
3890         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3891         for ( i = sym->regsUsed->size; i >= 0; i--) {
3892           if (bitVectBitValue(sym->regsUsed,i)) {
3893             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3894             _G.nRegsSaved--;
3895           }
3896         }
3897         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3898     }
3899
3900       
3901
3902     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3903           && sym->stack) {
3904       if (sym->stack == 1) {
3905         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3906         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3907       } else {
3908         // we have to add more than one...
3909         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3910         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3911         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3912         emitSKPNC;
3913         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3914         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3915         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3916       }
3917     }
3918
3919     if(strcmp(sym->name, "main")) {
3920       if(0
3921         || !options.ommitFramePtr
3922 //        || sym->regsUsed
3923         || IFFUNC_ARGS(sym->type)
3924         || FUNC_HASSTACKPARM(sym->etype)
3925         ) {
3926         /* restore stack frame */
3927         if(STACK_MODEL_LARGE)
3928           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3929         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3930       }
3931     }
3932
3933     _G.useWreg = 0;
3934
3935     if (IFFUNC_ISISR(sym->type)) {
3936       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3937       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3938       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3939       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3940
3941       if(!FUNC_ISSHADOWREGS(sym->type)) {
3942         /* do not restore interrupt vector for WREG,STATUS,BSR
3943          * for high priority interrupt, see genFunction */
3944         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3945         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3946         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3947       }
3948 //      _G.interruptvector = 0;         /* sanity check */
3949
3950
3951       /* if debug then send end of function */
3952 /*      if (options.debug && currFunc)  */
3953       if (currFunc) {
3954         debugFile->writeEndFunction (currFunc, ic, 1);
3955       }
3956         
3957       if(_G.usefastretfie)
3958         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3959       else
3960         pic16_emitpcodeNULLop(POC_RETFIE);
3961
3962       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3963       
3964       _G.usefastretfie = 0;
3965       return;
3966     }
3967
3968     if (IFFUNC_ISCRITICAL(sym->type)) {
3969       pic16_emitcode("setb","ea");
3970     }
3971
3972     /* if debug then send end of function */
3973     if (currFunc) {
3974       debugFile->writeEndFunction (currFunc, ic, 1);
3975     }
3976
3977     /* insert code to restore stack frame, if user enabled it
3978      * and function is not main() */
3979          
3980
3981     pic16_emitpcodeNULLop(POC_RETURN);
3982
3983     /* Mark the end of a function */
3984     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3985 }
3986
3987
3988 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3989 {
3990   unsigned long lit=1;
3991   operand *op;
3992
3993     op = IC_LEFT(ic);
3994   
3995     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3996     if(AOP_TYPE(op) == AOP_LIT) {
3997       if(!IS_FLOAT(operandType( op ))) {
3998         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3999       } else {
4000         union {
4001           unsigned long lit_int;
4002           float lit_float;
4003         } info;
4004         
4005         /* take care if literal is a float */
4006         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4007         lit = info.lit_int;
4008       }
4009     }
4010
4011     if(is_LitOp(op)) {
4012       if(/*(OP_LIVETO(op) <= ic->seq) &&*/ (lit == 0)) {
4013         pic16_emitpcode(POC_CLRF, dest);
4014       } else {
4015         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
4016         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
4017       }
4018     } else {
4019       if(dest->type == PO_WREG && (offset == 0)) {
4020         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4021       return;
4022     }
4023     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4024   }
4025 }
4026
4027 /*-----------------------------------------------------------------*/
4028 /* genRet - generate code for return statement                     */
4029 /*-----------------------------------------------------------------*/
4030 static void genRet (iCode *ic)
4031 {
4032   int size;
4033   operand *left;
4034
4035     FENTRY;
4036         /* if we have no return value then
4037          * just generate the "ret" */
4038         
4039         if (!IC_LEFT(ic)) 
4040                 goto jumpret;       
4041     
4042         /* we have something to return then
4043          * move the return value into place */
4044         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4045         size = AOP_SIZE(IC_LEFT(ic));
4046
4047         if(size <= 4) {
4048           if(size>3)
4049             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4050           
4051           if(size>2)
4052             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4053
4054           if(size>1)
4055             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4056           
4057           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4058
4059         } else {
4060                 /* >32-bits, setup stack and FSR0 */
4061                 while (size--) {
4062 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4063 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4064
4065                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4066
4067 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
4068                         GpsuedoStkPtr++;
4069                 }
4070                         
4071                 /* setup FSR0 */
4072                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4073                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4074
4075                 if(STACK_MODEL_LARGE) {
4076                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4077                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4078                 } else {
4079                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4080                 }
4081         }
4082                                 
4083 #if 0
4084         /* old code, left here for reference -- VR */    
4085         while (size--) {
4086           char *l ;
4087
4088                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4089                         /* #NOCHANGE */
4090                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4091                         pic16_emitpcomment("push %s",l);
4092                         pushed++;
4093                 } else {
4094                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4095                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4096                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4097                         
4098                         if (strcmp(fReturn[offset],l)) {
4099                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4100                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4101                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4102                                 } else {
4103                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4104                                 }
4105                                 
4106                                 if(size) {
4107                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4108                                 }
4109                                 offset++;
4110                         }
4111                 }
4112         }    
4113
4114         if (pushed) {
4115                 while(pushed) {
4116                         pushed--;
4117                         if (strcmp(fReturn[pushed],"a"))
4118                                 pic16_emitcode("pop",fReturn[pushed]);
4119                         else
4120                                 pic16_emitcode("pop","acc");
4121                 }
4122         }
4123 #endif
4124
4125
4126         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4127     
4128 jumpret:
4129         /* generate a jump to the return label
4130          * if the next is not the return statement */
4131         if (!(ic->next && ic->next->op == LABEL
4132                 && IC_LABEL(ic->next) == returnLabel)) {
4133         
4134                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4135                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4136         }
4137 }
4138
4139 /*-----------------------------------------------------------------*/
4140 /* genLabel - generates a label                                    */
4141 /*-----------------------------------------------------------------*/
4142 static void genLabel (iCode *ic)
4143 {
4144   FENTRY;
4145
4146   /* special case never generate */
4147   if (IC_LABEL(ic) == entryLabel)
4148     return ;
4149
4150   pic16_emitpLabel(IC_LABEL(ic)->key);
4151 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4152 }
4153
4154 /*-----------------------------------------------------------------*/
4155 /* genGoto - generates a goto                                      */
4156 /*-----------------------------------------------------------------*/
4157 //tsd
4158 static void genGoto (iCode *ic)
4159 {
4160   FENTRY;
4161   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4162 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4163 }
4164
4165
4166 /*-----------------------------------------------------------------*/
4167 /* genMultbits :- multiplication of bits                           */
4168 /*-----------------------------------------------------------------*/
4169 static void genMultbits (operand *left, 
4170                          operand *right, 
4171                          operand *result)
4172 {
4173   FENTRY;
4174
4175   if(!pic16_sameRegs(AOP(result),AOP(right)))
4176     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4177
4178   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4179   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4180   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4181
4182 }
4183
4184
4185 /*-----------------------------------------------------------------*/
4186 /* genMultOneByte : 8 bit multiplication & division                */
4187 /*-----------------------------------------------------------------*/
4188 static void genMultOneByte (operand *left,
4189                             operand *right,
4190                             operand *result)
4191 {
4192
4193   FENTRY;
4194   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4195   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4196
4197   /* (if two literals, the value is computed before) */
4198   /* if one literal, literal on the right */
4199   if (AOP_TYPE(left) == AOP_LIT){
4200     operand *t = right;
4201     right = left;
4202     left = t;
4203   }
4204
4205         /* size is already checked in genMult == 1 */
4206 //      size = AOP_SIZE(result);
4207
4208         if (AOP_TYPE(right) == AOP_LIT){
4209                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4210                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4211                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4212                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4213         } else {
4214                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4215                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4216                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4217                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4218         }
4219         
4220         pic16_genMult8X8_8 (left, right,result);
4221 }
4222
4223 /*-----------------------------------------------------------------*/
4224 /* genMultOneWord : 16 bit multiplication                          */
4225 /*-----------------------------------------------------------------*/
4226 static void genMultOneWord (operand *left,
4227                             operand *right,
4228                             operand *result)
4229 {
4230   FENTRY;
4231   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4232   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4233
4234   /* (if two literals, the value is computed before)
4235    * if one literal, literal on the right */
4236   if (AOP_TYPE(left) == AOP_LIT){
4237     operand *t = right;
4238     right = left;
4239     left = t;
4240   }
4241
4242   /* size is checked already == 2 */
4243 //  size = AOP_SIZE(result);
4244
4245   if (AOP_TYPE(right) == AOP_LIT) {
4246     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4247       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4248       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4249       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4250   } else {
4251     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4252       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4253       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4254       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4255   }
4256         
4257   pic16_genMult16X16_16(left, right,result);
4258 }
4259
4260 /*-----------------------------------------------------------------*/
4261 /* genMultOneLong : 32 bit multiplication                          */
4262 /*-----------------------------------------------------------------*/
4263 static void genMultOneLong (operand *left,
4264                             operand *right,
4265                             operand *result)
4266 {
4267   FENTRY;
4268   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4269   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4270
4271   /* (if two literals, the value is computed before)
4272    * if one literal, literal on the right */
4273   if (AOP_TYPE(left) == AOP_LIT){
4274     operand *t = right;
4275     right = left;
4276     left = t;
4277   }
4278
4279   /* size is checked already == 4 */
4280 //  size = AOP_SIZE(result);
4281
4282   if (AOP_TYPE(right) == AOP_LIT) {
4283     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4284         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4285         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4286         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4287   } else {
4288     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4289         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4290         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4291         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4292   }
4293         
4294   pic16_genMult32X32_32(left, right,result);
4295 }
4296
4297
4298
4299 /*-----------------------------------------------------------------*/
4300 /* genMult - generates code for multiplication                     */
4301 /*-----------------------------------------------------------------*/
4302 static void genMult (iCode *ic)
4303 {
4304   operand *left = IC_LEFT(ic);
4305   operand *right = IC_RIGHT(ic);
4306   operand *result= IC_RESULT(ic);   
4307
4308     FENTRY;
4309         /* assign the amsops */
4310         pic16_aopOp (left,ic,FALSE);
4311         pic16_aopOp (right,ic,FALSE);
4312         pic16_aopOp (result,ic,TRUE);
4313
4314         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4315
4316         /* special cases first *
4317         * both are bits */
4318         if (AOP_TYPE(left) == AOP_CRY
4319                 && AOP_TYPE(right)== AOP_CRY) {
4320                 genMultbits(left,right,result);
4321           goto release ;
4322         }
4323
4324         /* if both are of size == 1 */
4325         if(AOP_SIZE(left) == 1
4326                 && AOP_SIZE(right) == 1) {
4327                 genMultOneByte(left,right,result);
4328           goto release ;
4329         }
4330
4331         /* if both are of size == 2 */
4332         if(AOP_SIZE(left) == 2
4333                 && AOP_SIZE(right) == 2) {
4334                 genMultOneWord(left, right, result);
4335           goto release;
4336         }
4337         
4338         /* if both are of size == 4 */
4339         if(AOP_SIZE(left) == 4
4340                 && AOP_SIZE(right) == 4) {
4341                 genMultOneLong(left, right, result);
4342           goto release;
4343         }
4344         
4345         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4346
4347
4348         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4349         /* should have been converted to function call */
4350         assert(0) ;
4351
4352 release :
4353         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4354         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4355         pic16_freeAsmop(result,NULL,ic,TRUE); 
4356 }
4357
4358 /*-----------------------------------------------------------------*/
4359 /* genDivbits :- division of bits                                  */
4360 /*-----------------------------------------------------------------*/
4361 static void genDivbits (operand *left, 
4362                         operand *right, 
4363                         operand *result)
4364 {
4365   char *l;
4366
4367     FENTRY;
4368     /* the result must be bit */    
4369     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4370     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4371
4372     MOVA(l);    
4373
4374     pic16_emitcode("div","ab");
4375     pic16_emitcode("rrc","a");
4376     pic16_aopPut(AOP(result),"c",0);
4377 }
4378
4379 /*-----------------------------------------------------------------*/
4380 /* genDivOneByte : 8 bit division                                  */
4381 /*-----------------------------------------------------------------*/
4382 static void genDivOneByte (operand *left,
4383                            operand *right,
4384                            operand *result)
4385 {
4386   sym_link *opetype = operandType(result);
4387   char *l ;
4388   symbol *lbl ;
4389   int size,offset;
4390
4391         /* result = divident / divisor
4392          * - divident may be a register or a literal,
4393          * - divisor may be a register or a literal,
4394          * so there are 3 cases (literal / literal is optimized
4395          * by the front-end) to handle.
4396          * In addition we must handle signed and unsigned, which
4397          * result in 6 final different cases -- VR */
4398
4399     FENTRY;
4400     
4401     size = AOP_SIZE(result) - 1;
4402     offset = 1;
4403     /* signed or unsigned */
4404     if (SPEC_USIGN(opetype)) {
4405       pCodeOp *pct1,    /* count */
4406                 *pct2,  /* reste */
4407                 *pct3;  /* temp */
4408       symbol *label1, *label2, *label3;;
4409
4410
4411         /* unsigned is easy */
4412
4413         pct1 = pic16_popGetTempReg(1);
4414         pct2 = pic16_popGetTempReg(1);
4415         pct3 = pic16_popGetTempReg(1);
4416         
4417         label1 = newiTempLabel(NULL);
4418         label2 = newiTempLabel(NULL);
4419         label3 = newiTempLabel(NULL);
4420
4421         /* the following algorithm is extracted from divuint.c */
4422
4423         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4424         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4425         
4426         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4427
4428         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4429         
4430         pic16_emitpLabel(label1->key);
4431         
4432         emitCLRC;
4433         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4434
4435
4436         emitCLRC;
4437         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4438         
4439
4440         emitSKPNC;
4441         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4442         
4443         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4444         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4445         
4446         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4447         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4448         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4449         
4450         pic16_emitpLabel( label3->key );
4451         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4452         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4453         
4454         
4455
4456         pic16_emitpLabel(label2->key);
4457         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4458         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4459         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4460         
4461         /* result is in wreg */
4462         if(AOP_TYPE(result) != AOP_ACC)
4463                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4464
4465         pic16_popReleaseTempReg( pct3, 1);
4466         pic16_popReleaseTempReg( pct2, 1);
4467         pic16_popReleaseTempReg( pct1, 1);
4468
4469         return ;
4470     }
4471
4472     /* signed is a little bit more difficult */
4473
4474     /* save the signs of the operands */
4475     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4476     MOVA(l);    
4477     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4478     pic16_emitcode("push","acc"); /* save it on the stack */
4479
4480     /* now sign adjust for both left & right */
4481     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4482     MOVA(l);       
4483     lbl = newiTempLabel(NULL);
4484     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4485     pic16_emitcode("cpl","a");   
4486     pic16_emitcode("inc","a");
4487     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4488     pic16_emitcode("mov","b,a");
4489
4490     /* sign adjust left side */
4491     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4492     MOVA(l);
4493
4494     lbl = newiTempLabel(NULL);
4495     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4496     pic16_emitcode("cpl","a");
4497     pic16_emitcode("inc","a");
4498     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4499
4500     /* now the division */
4501     pic16_emitcode("div","ab");
4502     /* we are interested in the lower order
4503     only */
4504     pic16_emitcode("mov","b,a");
4505     lbl = newiTempLabel(NULL);
4506     pic16_emitcode("pop","acc");   
4507     /* if there was an over flow we don't 
4508     adjust the sign of the result */
4509     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4510     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4511     CLRC;
4512     pic16_emitcode("clr","a");
4513     pic16_emitcode("subb","a,b");
4514     pic16_emitcode("mov","b,a");
4515     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4516
4517     /* now we are done */
4518     pic16_aopPut(AOP(result),"b",0);
4519     if(size > 0){
4520         pic16_emitcode("mov","c,b.7");
4521         pic16_emitcode("subb","a,acc");   
4522     }
4523     while (size--)
4524         pic16_aopPut(AOP(result),"a",offset++);
4525
4526 }
4527
4528 /*-----------------------------------------------------------------*/
4529 /* genDiv - generates code for division                            */
4530 /*-----------------------------------------------------------------*/
4531 static void genDiv (iCode *ic)
4532 {
4533     operand *left = IC_LEFT(ic);
4534     operand *right = IC_RIGHT(ic);
4535     operand *result= IC_RESULT(ic);   
4536
4537
4538         /* Division is a very lengthy algorithm, so it is better
4539          * to call support routines than inlining algorithm.
4540          * Division functions written here just in case someone
4541          * wants to inline and not use the support libraries -- VR */
4542
4543     FENTRY;
4544     
4545     /* assign the amsops */
4546     pic16_aopOp (left,ic,FALSE);
4547     pic16_aopOp (right,ic,FALSE);
4548     pic16_aopOp (result,ic,TRUE);
4549
4550     /* special cases first */
4551     /* both are bits */
4552     if (AOP_TYPE(left) == AOP_CRY &&
4553         AOP_TYPE(right)== AOP_CRY) {
4554         genDivbits(left,right,result);
4555         goto release ;
4556     }
4557
4558     /* if both are of size == 1 */
4559     if (AOP_SIZE(left) == 1 &&
4560         AOP_SIZE(right) == 1 ) {
4561         genDivOneByte(left,right,result);
4562         goto release ;
4563     }
4564
4565     /* should have been converted to function call */
4566     assert(0);
4567 release :
4568     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4569     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4570     pic16_freeAsmop(result,NULL,ic,TRUE); 
4571 }
4572
4573 /*-----------------------------------------------------------------*/
4574 /* genModbits :- modulus of bits                                   */
4575 /*-----------------------------------------------------------------*/
4576 static void genModbits (operand *left, 
4577                         operand *right, 
4578                         operand *result)
4579 {
4580   char *l;
4581
4582     FENTRY;  
4583     
4584     werror(W_POSSBUG2, __FILE__, __LINE__);
4585     /* the result must be bit */    
4586     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4587     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4588
4589     MOVA(l);       
4590
4591     pic16_emitcode("div","ab");
4592     pic16_emitcode("mov","a,b");
4593     pic16_emitcode("rrc","a");
4594     pic16_aopPut(AOP(result),"c",0);
4595 }
4596
4597 /*-----------------------------------------------------------------*/
4598 /* genModOneByte : 8 bit modulus                                   */
4599 /*-----------------------------------------------------------------*/
4600 static void genModOneByte (operand *left,
4601                            operand *right,
4602                            operand *result)
4603 {
4604   sym_link *opetype = operandType(result);
4605   char *l ;
4606   symbol *lbl ;
4607
4608     FENTRY;
4609     werror(W_POSSBUG2, __FILE__, __LINE__);
4610
4611     /* signed or unsigned */
4612     if (SPEC_USIGN(opetype)) {
4613         /* unsigned is easy */
4614         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4615         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4616         MOVA(l);    
4617         pic16_emitcode("div","ab");
4618         pic16_aopPut(AOP(result),"b",0);
4619         return ;
4620     }
4621
4622     /* signed is a little bit more difficult */
4623
4624     /* save the signs of the operands */
4625     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4626     MOVA(l);
4627
4628     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4629     pic16_emitcode("push","acc"); /* save it on the stack */
4630
4631     /* now sign adjust for both left & right */
4632     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4633     MOVA(l);
4634
4635     lbl = newiTempLabel(NULL);
4636     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4637     pic16_emitcode("cpl","a");   
4638     pic16_emitcode("inc","a");
4639     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4640     pic16_emitcode("mov","b,a"); 
4641
4642     /* sign adjust left side */
4643     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4644     MOVA(l);
4645
4646     lbl = newiTempLabel(NULL);
4647     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4648     pic16_emitcode("cpl","a");   
4649     pic16_emitcode("inc","a");
4650     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4651
4652     /* now the multiplication */
4653     pic16_emitcode("div","ab");
4654     /* we are interested in the lower order
4655     only */
4656     lbl = newiTempLabel(NULL);
4657     pic16_emitcode("pop","acc");   
4658     /* if there was an over flow we don't 
4659     adjust the sign of the result */
4660     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4661     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4662     CLRC ;
4663     pic16_emitcode("clr","a");
4664     pic16_emitcode("subb","a,b");
4665     pic16_emitcode("mov","b,a");
4666     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4667
4668     /* now we are done */
4669     pic16_aopPut(AOP(result),"b",0);
4670
4671 }
4672
4673 /*-----------------------------------------------------------------*/
4674 /* genMod - generates code for division                            */
4675 /*-----------------------------------------------------------------*/
4676 static void genMod (iCode *ic)
4677 {
4678   operand *left = IC_LEFT(ic);
4679   operand *right = IC_RIGHT(ic);
4680   operand *result= IC_RESULT(ic);  
4681
4682     FENTRY;
4683     
4684     /* assign the amsops */
4685     pic16_aopOp (left,ic,FALSE);
4686     pic16_aopOp (right,ic,FALSE);
4687     pic16_aopOp (result,ic,TRUE);
4688
4689     /* special cases first */
4690     /* both are bits */
4691     if (AOP_TYPE(left) == AOP_CRY &&
4692         AOP_TYPE(right)== AOP_CRY) {
4693         genModbits(left,right,result);
4694         goto release ;
4695     }
4696
4697     /* if both are of size == 1 */
4698     if (AOP_SIZE(left) == 1 &&
4699         AOP_SIZE(right) == 1 ) {
4700         genModOneByte(left,right,result);
4701         goto release ;
4702     }
4703
4704     /* should have been converted to function call */
4705     assert(0);
4706
4707 release :
4708     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4709     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4710     pic16_freeAsmop(result,NULL,ic,TRUE); 
4711 }
4712
4713 /*-----------------------------------------------------------------*/
4714 /* genIfxJump :- will create a jump depending on the ifx           */
4715 /*-----------------------------------------------------------------*/
4716 /*
4717   note: May need to add parameter to indicate when a variable is in bit space.
4718 */
4719 static void genIfxJump (iCode *ic, char *jval)
4720 {
4721   FENTRY;
4722   
4723     /* if true label then we jump if condition
4724     supplied is true */
4725     if ( IC_TRUE(ic) ) {
4726
4727         if(strcmp(jval,"a") == 0)
4728           emitSKPZ;
4729         else if (strcmp(jval,"c") == 0)
4730           emitSKPNC;
4731         else {
4732           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4733           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4734         }
4735
4736         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4737         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4738
4739     }
4740     else {
4741         /* false label is present */
4742         if(strcmp(jval,"a") == 0)
4743           emitSKPNZ;
4744         else if (strcmp(jval,"c") == 0)
4745           emitSKPC;
4746         else {
4747           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4748           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4749         }
4750
4751         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4752         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4753
4754     }
4755
4756
4757     /* mark the icode as generated */
4758     ic->generated = 1;
4759 }
4760
4761 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4762 {
4763   FENTRY;
4764   
4765     /* if true label then we jump if condition
4766     supplied is true */
4767     if ( IC_TRUE(ic) ) {
4768       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4769       pic16_emitpcode(POC_BTFSC, jop);
4770
4771       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4772       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4773
4774     } else {
4775       /* false label is present */
4776       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4777       pic16_emitpcode(POC_BTFSS, jop);
4778           
4779       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4780       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4781     }
4782
4783
4784     /* mark the icode as generated */
4785     ic->generated = 1;
4786 }
4787
4788 #if 0
4789 // not needed ATM
4790
4791 /*-----------------------------------------------------------------*/
4792 /* genSkip                                                         */
4793 /*-----------------------------------------------------------------*/
4794 static void genSkip(iCode *ifx,int status_bit)
4795 {
4796   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4797   if(!ifx)
4798     return;
4799
4800   if ( IC_TRUE(ifx) ) {
4801     switch(status_bit) {
4802     case 'z':
4803       emitSKPNZ;
4804       break;
4805
4806     case 'c':
4807       emitSKPNC;
4808       break;
4809
4810     case 'd':
4811       emitSKPDC;
4812       break;
4813
4814     }
4815
4816     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4817     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4818
4819   } else {
4820
4821     switch(status_bit) {
4822
4823     case 'z':
4824       emitSKPZ;
4825       break;
4826
4827     case 'c':
4828       emitSKPC;
4829       break;
4830
4831     case 'd':
4832       emitSKPDC;
4833       break;
4834     }
4835     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4836     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4837
4838   }
4839
4840 }
4841 #endif
4842
4843 /*-----------------------------------------------------------------*/
4844 /* genSkipc                                                        */
4845 /*-----------------------------------------------------------------*/
4846 static void genSkipc(resolvedIfx *rifx)
4847 {
4848   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4849   
4850   if(!rifx)
4851     return;
4852
4853   if(rifx->condition)
4854     emitSKPNC;
4855   else
4856     emitSKPC;
4857
4858   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4859   rifx->generated = 1;
4860 }
4861
4862 #if !(USE_SIMPLE_GENCMP)
4863 /*-----------------------------------------------------------------*/
4864 /* genSkipz2                                                       */
4865 /*-----------------------------------------------------------------*/
4866 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4867 {
4868   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4869   
4870   if(!rifx)
4871     return;
4872
4873   if( (rifx->condition ^ invert_condition) & 1)
4874     emitSKPZ;
4875   else
4876     emitSKPNZ;
4877
4878   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4879   rifx->generated = 1;
4880 }
4881 #endif
4882
4883 #if 0
4884 /*-----------------------------------------------------------------*/
4885 /* genSkipz                                                        */
4886 /*-----------------------------------------------------------------*/
4887 static void genSkipz(iCode *ifx, int condition)
4888 {
4889   if(!ifx)
4890     return;
4891
4892   if(condition)
4893     emitSKPNZ;
4894   else
4895     emitSKPZ;
4896
4897   if ( IC_TRUE(ifx) )
4898     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4899   else
4900     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4901
4902   if ( IC_TRUE(ifx) )
4903     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4904   else
4905     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4906
4907 }
4908 #endif
4909
4910 #if !(USE_SIMPLE_GENCMP)
4911 /*-----------------------------------------------------------------*/
4912 /* genSkipCond                                                     */
4913 /*-----------------------------------------------------------------*/
4914 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4915 {
4916   if(!rifx)
4917     return;
4918
4919   if(rifx->condition)
4920     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4921   else
4922     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4923
4924
4925   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4926   rifx->generated = 1;
4927 }
4928 #endif
4929
4930 #if 0
4931 /*-----------------------------------------------------------------*/
4932 /* genChkZeroes :- greater or less than comparison                 */
4933 /*     For each byte in a literal that is zero, inclusive or the   */
4934 /*     the corresponding byte in the operand with W                */
4935 /*     returns true if any of the bytes are zero                   */
4936 /*-----------------------------------------------------------------*/
4937 static int genChkZeroes(operand *op, int lit,  int size)
4938 {
4939
4940   int i;
4941   int flag =1;
4942
4943   while(size--) {
4944     i = (lit >> (size*8)) & 0xff;
4945
4946     if(i==0) {
4947       if(flag) 
4948         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4949       else
4950         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4951       flag = 0;
4952     }
4953   }
4954
4955   return (flag==0);
4956 }
4957 #endif
4958
4959
4960 /*-----------------------------------------------------------------*/
4961 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4962 /*                  aop (if it's NOT a literal) or from lit (if    */
4963 /*                  aop is a literal)                              */
4964 /*-----------------------------------------------------------------*/
4965 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4966   if (aop->type == AOP_LIT) {
4967     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4968   } else {
4969     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4970   }
4971 }
4972
4973 /*-----------------------------------------------------------------*/
4974 /* genCmp :- greater or less than comparison                       */
4975 /*-----------------------------------------------------------------*/
4976
4977 #if USE_SIMPLE_GENCMP           /* { */
4978
4979 /* genCmp performs a left < right comparison, stores
4980  * the outcome in result (if != NULL) and generates
4981  * control flow code for the ifx (if != NULL).
4982  *
4983  * This version leaves in sequences like
4984  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4985  * which should be optmized by the peephole
4986  * optimizer - RN 2005-01-01 */
4987 static void genCmp (operand *left,operand *right,
4988                     operand *result, iCode *ifx, int sign)
4989 {
4990   resolvedIfx rIfx;
4991   int size;
4992   int offs;
4993   symbol *templbl;
4994   operand *dummy;
4995   unsigned long lit;
4996   unsigned long mask;
4997   int performedLt;
4998
4999   FENTRY;
5000   
5001   assert (AOP_SIZE(left) == AOP_SIZE(right));
5002   assert (left && right);
5003
5004   size = AOP_SIZE(right) - 1;
5005   mask = (0x100UL << (size*8)) - 1;
5006   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5007   performedLt = 1;
5008   templbl = NULL;
5009   lit = 0;
5010   
5011   resolveIfx (&rIfx, ifx);
5012
5013   /* handle for special cases */
5014   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5015       return;
5016
5017   /**********************************************************************
5018    * handle bits - bit compares are promoted to int compares seemingly! *
5019    **********************************************************************/
5020 #if 0
5021   // THIS IS COMPLETELY UNTESTED!
5022   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5023     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5024     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5025     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5026
5027     emitSETC;
5028     // 1 < {0,1} is false --> clear C by skipping the next instruction
5029     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5030     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5031     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5032     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5033     emitCLRC; // only skipped for left=0 && right=1
5034
5035     goto correct_result_in_carry;
5036   } // if
5037 #endif
5038
5039   /*************************************************
5040    * make sure that left is register (or the like) *
5041    *************************************************/
5042   if (!isAOP_REGlike(left)) {
5043     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5044     assert (isAOP_LIT(left));
5045     assert (isAOP_REGlike(right));
5046     // swap left and right
5047     // left < right <==> right > left <==> (right >= left + 1)
5048     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5049
5050     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5051       // MAXVALUE < right? always false
5052       if (performedLt) emitCLRC; else emitSETC;
5053       goto correct_result_in_carry;
5054     } // if
5055
5056     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5057     // that's why we handled it above.
5058     lit++;
5059
5060     dummy = left;
5061     left = right;
5062     right = dummy;
5063
5064     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5065   } else if (isAOP_LIT(right)) {
5066     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5067   } // if
5068
5069   assert (isAOP_REGlike(left)); // left must be register or the like
5070   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5071
5072   /*************************************************
5073    * special cases go here                         *
5074    *************************************************/
5075
5076   if (isAOP_LIT(right)) {
5077     if (!sign) {
5078       // unsigned comparison to a literal
5079       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5080       if (lit == 0) {
5081         // unsigned left < 0? always false
5082         if (performedLt) emitCLRC; else emitSETC;
5083         goto correct_result_in_carry;
5084       }
5085     } else {
5086       // signed comparison to a literal
5087       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5088       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5089         // signed left < 0x80000000? always false
5090         if (performedLt) emitCLRC; else emitSETC;
5091         goto correct_result_in_carry;
5092       } else if (lit == 0) {
5093         // compare left < 0; set CARRY if SIGNBIT(left) is set
5094         if (performedLt) emitSETC; else emitCLRC;
5095         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5096         if (performedLt) emitCLRC; else emitSETC;
5097         goto correct_result_in_carry;
5098       }
5099     } // if (!sign)
5100   } // right is literal
5101
5102   /*************************************************
5103    * perform a general case comparison             *
5104    * make sure we get CARRY==1 <==> left >= right  *
5105    *************************************************/
5106   // compare most significant bytes
5107   //DEBUGpc ("comparing bytes at offset %d", size);
5108   if (!sign) {
5109     // unsigned comparison
5110     mov2w_regOrLit (AOP(right), lit, size);
5111     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5112   } else {
5113     // signed comparison
5114     // (add 2^n to both operands then perform an unsigned comparison)
5115     if (isAOP_LIT(right)) {
5116       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5117       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5118
5119       if (litbyte == 0x80) {
5120         // left >= 0x80 -- always true, but more bytes to come
5121         pic16_mov2w (AOP(left), size);
5122         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5123         emitSETC;
5124       } else {
5125         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5126         pic16_mov2w (AOP(left), size);
5127         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5128         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5129       } // if
5130     } else {
5131       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5132       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5133       pic16_mov2w (AOP(left), size);
5134       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5135       pic16_emitpcode (POC_MOVWF, pctemp);
5136       pic16_mov2w (AOP(right), size);
5137       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5138       pic16_emitpcode (POC_SUBFW, pctemp);
5139       //pic16_popReleaseTempReg(pctemp, 1);
5140     }
5141   } // if (!sign)
5142
5143   // compare remaining bytes (treat as unsigned case from above)
5144   templbl = newiTempLabel ( NULL );
5145   offs = size;
5146   while (offs--) {
5147     //DEBUGpc ("comparing bytes at offset %d", offs);
5148     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5149     mov2w_regOrLit (AOP(right), lit, offs);
5150     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5151   } // while (offs)
5152   pic16_emitpLabel (templbl->key);
5153   goto result_in_carry;
5154
5155 result_in_carry:
5156   
5157   /****************************************************
5158    * now CARRY contains the result of the comparison: *
5159    * SUBWF sets CARRY iff                             *
5160    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5161    * (F=left, W=right)                                *
5162    ****************************************************/
5163
5164   if (performedLt) {
5165     if (result && AOP_TYPE(result) != AOP_CRY) {
5166       // value will be stored
5167       emitTOGC;
5168     } else {
5169       // value wil only be used in the following genSkipc()
5170       rIfx.condition ^= 1;
5171     }
5172   } // if
5173
5174 correct_result_in_carry:
5175
5176   // assign result to variable (if neccessary)
5177   if (result && AOP_TYPE(result) != AOP_CRY) {
5178     //DEBUGpc ("assign result");
5179     size = AOP_SIZE(result);
5180     while (size--) {
5181       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5182     } // while
5183     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5184   } // if (result)
5185
5186   // perform conditional jump
5187   if (ifx) {
5188     //DEBUGpc ("generate control flow");
5189     genSkipc (&rIfx);
5190     ifx->generated = 1;
5191   } // if
5192 }
5193
5194 #elif 1         /* } */
5195                 /* { */
5196       /* original code */
5197 static void genCmp (operand *left,operand *right,
5198                     operand *result, iCode *ifx, int sign)
5199 {
5200   int size; //, offset = 0 ;
5201   unsigned long lit = 0L,i = 0;
5202   resolvedIfx rFalseIfx;
5203   //  resolvedIfx rTrueIfx;
5204   symbol *truelbl;
5205   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5206 /*
5207   if(ifx) {
5208     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5209     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5210   }
5211 */
5212
5213   FENTRY;
5214   
5215   resolveIfx(&rFalseIfx,ifx);
5216   truelbl  = newiTempLabel(NULL);
5217   size = max(AOP_SIZE(left),AOP_SIZE(right));
5218
5219   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5220
5221 #define _swapp
5222
5223   /* if literal is on the right then swap with left */
5224   if ((AOP_TYPE(right) == AOP_LIT)) {
5225     operand *tmp = right ;
5226     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5227     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5228 #ifdef _swapp
5229
5230     lit = (lit - 1) & mask;
5231     right = left;
5232     left = tmp;
5233     rFalseIfx.condition ^= 1;
5234 #endif
5235
5236   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5237     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5238   }
5239
5240
5241   //if(IC_TRUE(ifx) == NULL)
5242   /* if left & right are bit variables */
5243   if (AOP_TYPE(left) == AOP_CRY &&
5244       AOP_TYPE(right) == AOP_CRY ) {
5245     assert (0 && "bit variables used in genCmp");
5246     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5247     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5248   } else {
5249     /* subtract right from left if at the
5250        end the carry flag is set then we know that
5251        left is greater than right */
5252
5253     symbol *lbl  = newiTempLabel(NULL);
5254
5255 #if 0
5256         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5257                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5258 #endif
5259
5260 #ifndef _swapp
5261     if(AOP_TYPE(right) == AOP_LIT) {
5262
5263       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5264
5265       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5266
5267       /* special cases */
5268
5269       if(lit == 0) {
5270
5271         if(sign != 0) 
5272           genSkipCond(&rFalseIfx,left,size-1,7);
5273         else 
5274           /* no need to compare to 0...*/
5275           /* NOTE: this is a de-generate compare that most certainly 
5276            *       creates some dead code. */
5277           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5278
5279         if(ifx) ifx->generated = 1;
5280         return;
5281
5282       }
5283       size--;
5284
5285       if(size == 0) {
5286         //i = (lit >> (size*8)) & 0xff;
5287         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5288         
5289         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5290
5291         i = ((0-lit) & 0xff);
5292         if(sign) {
5293           if( i == 0x81) { 
5294             /* lit is 0x7f, all signed chars are less than
5295              * this except for 0x7f itself */
5296             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5297             genSkipz2(&rFalseIfx,0);
5298           } else {
5299             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5300             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5301             genSkipc(&rFalseIfx);
5302           }
5303
5304         } else {
5305           if(lit == 1) {
5306             genSkipz2(&rFalseIfx,1);
5307           } else {
5308             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5309             genSkipc(&rFalseIfx);
5310           }
5311         }
5312
5313         if(ifx) ifx->generated = 1;
5314         return;
5315       }
5316
5317       /* chars are out of the way. now do ints and longs */
5318
5319
5320       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5321         
5322       /* special cases */
5323
5324       if(sign) {
5325
5326         if(lit == 0) {
5327           genSkipCond(&rFalseIfx,left,size,7);
5328           if(ifx) ifx->generated = 1;
5329           return;
5330         }
5331
5332         if(lit <0x100) {
5333           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5334
5335           //rFalseIfx.condition ^= 1;
5336           //genSkipCond(&rFalseIfx,left,size,7);
5337           //rFalseIfx.condition ^= 1;
5338
5339           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5340           if(rFalseIfx.condition)
5341             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5342           else
5343             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5344
5345           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5346           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5347           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5348
5349           while(size > 1)
5350             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5351
5352           if(rFalseIfx.condition) {
5353             emitSKPZ;
5354             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5355
5356           } else {
5357             emitSKPNZ;
5358           }
5359
5360           genSkipc(&rFalseIfx);
5361           pic16_emitpLabel(truelbl->key);
5362           if(ifx) ifx->generated = 1;
5363           return;
5364
5365         }
5366
5367         if(size == 1) {
5368
5369           if( (lit & 0xff) == 0) {
5370             /* lower byte is zero */
5371             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5372             i = ((lit >> 8) & 0xff) ^0x80;
5373             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5374             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5375             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5376             genSkipc(&rFalseIfx);
5377
5378
5379             if(ifx) ifx->generated = 1;
5380             return;
5381
5382           }
5383         } else {
5384           /* Special cases for signed longs */
5385           if( (lit & 0xffffff) == 0) {
5386             /* lower byte is zero */
5387             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5388             i = ((lit >> 8*3) & 0xff) ^0x80;
5389             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5390             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5391             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5392             genSkipc(&rFalseIfx);
5393
5394
5395             if(ifx) ifx->generated = 1;
5396             return;
5397
5398           }
5399
5400         }
5401
5402
5403         if(lit & (0x80 << (size*8))) {
5404           /* lit is negative */
5405           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5406
5407           //genSkipCond(&rFalseIfx,left,size,7);
5408
5409           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5410
5411           if(rFalseIfx.condition)
5412             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5413           else
5414             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5415
5416
5417         } else {
5418           /* lit is positive */
5419           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5420           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5421           if(rFalseIfx.condition)
5422             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5423           else
5424             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5425
5426         }
5427
5428         /*
5429           This works, but is only good for ints.
5430           It also requires a "known zero" register.
5431           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5432           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5433           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5434           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5435           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5436           genSkipc(&rFalseIfx);
5437
5438           pic16_emitpLabel(truelbl->key);
5439           if(ifx) ifx->generated = 1;
5440           return;
5441         **/
5442           
5443         /* There are no more special cases, so perform a general compare */
5444   
5445         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5446         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5447
5448         while(size--) {
5449
5450           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5451           emitSKPNZ;
5452           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5453         }
5454         //rFalseIfx.condition ^= 1;
5455         genSkipc(&rFalseIfx);
5456
5457         pic16_emitpLabel(truelbl->key);
5458
5459         if(ifx) ifx->generated = 1;
5460         return;
5461
5462
5463       }
5464
5465
5466       /* sign is out of the way. So now do an unsigned compare */
5467       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5468
5469
5470       /* General case - compare to an unsigned literal on the right.*/
5471
5472       i = (lit >> (size*8)) & 0xff;
5473       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5474       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5475       while(size--) {
5476         i = (lit >> (size*8)) & 0xff;
5477
5478         if(i) {
5479           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5480           emitSKPNZ;
5481           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5482         } else {
5483           /* this byte of the lit is zero, 
5484            *if it's not the last then OR in the variable */
5485           if(size)
5486             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5487         }
5488       }
5489
5490
5491       pic16_emitpLabel(lbl->key);
5492 //      pic16_emitpLabel(truelbl->key);
5493       //if(emitFinalCheck)
5494       genSkipc(&rFalseIfx);
5495       if(sign)
5496         pic16_emitpLabel(truelbl->key);
5497
5498       if(ifx) ifx->generated = 1;
5499       return;
5500
5501
5502     }
5503 #endif  // _swapp
5504
5505     if(AOP_TYPE(left) == AOP_LIT) {
5506       //symbol *lbl = newiTempLabel(NULL);
5507
5508       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5509
5510
5511       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5512
5513       /* Special cases */
5514       if((lit == 0) && (sign == 0)){
5515
5516         size--;
5517         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5518         while(size) 
5519           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5520
5521         genSkipz2(&rFalseIfx,0);
5522         if(ifx) ifx->generated = 1;
5523         return;
5524       }
5525
5526       if(size==1) {
5527         /* Special cases */
5528         lit &= 0xff;
5529         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5530           /* degenerate compare can never be true */
5531           if(rFalseIfx.condition == 0)
5532             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5533
5534           if(ifx) ifx->generated = 1;
5535           return;
5536         }
5537
5538         if(sign) {
5539           /* signed comparisons to a literal byte */
5540
5541           int lp1 = (lit+1) & 0xff;
5542
5543           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5544           switch (lp1) {
5545           case 0:
5546             rFalseIfx.condition ^= 1;
5547             genSkipCond(&rFalseIfx,right,0,7);
5548             break;
5549           case 0x7f:
5550             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5551             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5552             genSkipz2(&rFalseIfx,1);
5553             break;
5554           default:
5555             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5556             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5557             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5558             rFalseIfx.condition ^= 1;
5559             genSkipc(&rFalseIfx);
5560             break;
5561           }
5562         } else {
5563           /* unsigned comparisons to a literal byte */
5564
5565           switch(lit & 0xff ) {
5566           case 0:
5567             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5568             genSkipz2(&rFalseIfx,0);
5569             break;
5570           case 0x7f:
5571             rFalseIfx.condition ^= 1;
5572             genSkipCond(&rFalseIfx,right,0,7);
5573             break;
5574
5575           default:
5576             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5577             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5578             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5579             rFalseIfx.condition ^= 1;
5580             if (AOP_TYPE(result) == AOP_CRY)
5581               genSkipc(&rFalseIfx);
5582             else {
5583               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5584               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5585             }         
5586             break;
5587           }
5588         }
5589
5590         if(ifx) ifx->generated = 1;
5591         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5592                 goto check_carry;
5593         return;
5594
5595       } else {
5596
5597         /* Size is greater than 1 */
5598
5599         if(sign) {
5600           int lp1 = lit+1;
5601
5602           size--;
5603
5604           if(lp1 == 0) {
5605             /* this means lit = 0xffffffff, or -1 */
5606
5607
5608             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5609             rFalseIfx.condition ^= 1;
5610             genSkipCond(&rFalseIfx,right,size,7);
5611             if(ifx) ifx->generated = 1;
5612
5613             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5614               goto check_carry;
5615
5616             return;
5617           }
5618
5619           if(lit == 0) {
5620             int s = size;
5621
5622             if(rFalseIfx.condition) {
5623               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5624               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5625             }
5626
5627             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5628             while(size--)
5629               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5630
5631
5632             emitSKPZ;
5633             if(rFalseIfx.condition) {
5634               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5635               pic16_emitpLabel(truelbl->key);
5636             }else {
5637               rFalseIfx.condition ^= 1;
5638               genSkipCond(&rFalseIfx,right,s,7);
5639             }
5640
5641             if(ifx) ifx->generated = 1;
5642
5643             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5644               goto check_carry;
5645
5646             return;
5647           }
5648
5649           if((size == 1) &&  (0 == (lp1&0xff))) {
5650             /* lower byte of signed word is zero */
5651             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5652             i = ((lp1 >> 8) & 0xff) ^0x80;
5653             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5654             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5655             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5656
5657             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5658               emitTOGC;
5659               if(ifx) ifx->generated = 1;
5660               goto check_carry;
5661             } else {
5662               rFalseIfx.condition ^= 1;
5663               genSkipc(&rFalseIfx);
5664               if(ifx) ifx->generated = 1;
5665             }
5666
5667             return;
5668           }
5669
5670           if(lit & (0x80 << (size*8))) {
5671             /* Lit is less than zero */
5672             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5673             //rFalseIfx.condition ^= 1;
5674             //genSkipCond(&rFalseIfx,left,size,7);
5675             //rFalseIfx.condition ^= 1;
5676             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5677             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5678
5679             if(rFalseIfx.condition)
5680               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5681             else
5682               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5683
5684
5685           } else {
5686             /* Lit is greater than or equal to zero */
5687             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5688             //rFalseIfx.condition ^= 1;
5689             //genSkipCond(&rFalseIfx,right,size,7);
5690             //rFalseIfx.condition ^= 1;
5691
5692             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5693             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5694
5695             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5696             if(rFalseIfx.condition)
5697               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5698             else
5699               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5700
5701           }
5702
5703           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5704           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5705
5706           while(size--) {
5707
5708             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5709             emitSKPNZ;
5710             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5711           }
5712           rFalseIfx.condition ^= 1;
5713           //rFalseIfx.condition = 1;
5714           genSkipc(&rFalseIfx);
5715
5716           pic16_emitpLabel(truelbl->key);
5717
5718           if(ifx) ifx->generated = 1;
5719
5720
5721           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5722             goto check_carry;
5723
5724           return;
5725           // end of if (sign)
5726         } else {
5727
5728           /* compare word or long to an unsigned literal on the right.*/
5729
5730
5731           size--;
5732           if(lit < 0xff) {
5733             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5734             switch (lit) {
5735             case 0:
5736               break; /* handled above */
5737 /*
5738             case 0xff:
5739               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5740               while(size--)
5741                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5742               genSkipz2(&rFalseIfx,0);
5743               break;
5744 */
5745             default:
5746               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5747               while(--size)
5748                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5749
5750               emitSKPZ;
5751               if(rFalseIfx.condition)
5752                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5753               else
5754                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5755
5756
5757               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5758               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5759
5760               rFalseIfx.condition ^= 1;
5761               genSkipc(&rFalseIfx);
5762             }
5763
5764             pic16_emitpLabel(truelbl->key);
5765
5766             if(ifx) ifx->generated = 1;
5767
5768             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5769               goto check_carry;
5770
5771             return;
5772           }
5773
5774
5775           lit++;
5776           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5777           i = (lit >> (size*8)) & 0xff;
5778
5779           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5780           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5781
5782           while(size--) {
5783             i = (lit >> (size*8)) & 0xff;
5784
5785             if(i) {
5786               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5787               emitSKPNZ;
5788               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5789             } else {
5790               /* this byte of the lit is zero, 
5791                * if it's not the last then OR in the variable */
5792               if(size)
5793                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5794             }
5795           }
5796
5797
5798           pic16_emitpLabel(lbl->key);
5799
5800           rFalseIfx.condition ^= 1;
5801
5802           genSkipc(&rFalseIfx);
5803         }
5804
5805         if(sign)
5806           pic16_emitpLabel(truelbl->key);
5807         if(ifx) ifx->generated = 1;
5808
5809             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5810               goto check_carry;
5811
5812         return;
5813       }
5814     }
5815     /* Compare two variables */
5816
5817     DEBUGpic16_emitcode(";sign","%d",sign);
5818
5819     size--;
5820     if(sign) {
5821       /* Sigh. thus sucks... */
5822       if(size) {
5823         pCodeOp *pctemp;
5824         
5825         pctemp = pic16_popGetTempReg(1);
5826         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5827         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5828         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5829         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5830         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5831         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5832         pic16_popReleaseTempReg(pctemp, 1);
5833       } else {
5834         /* Signed char comparison */
5835         /* Special thanks to Nikolai Golovchenko for this snippet */
5836         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5837         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5838         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5839         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5840         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5841         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5842
5843         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5844         genSkipc(&rFalseIfx);
5845           
5846         if(ifx) ifx->generated = 1;
5847
5848             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5849               goto check_carry;
5850
5851         return;
5852       }
5853
5854     } else {
5855
5856       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5857       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5858     }
5859
5860
5861     /* The rest of the bytes of a multi-byte compare */
5862     while (size) {
5863
5864       emitSKPZ;
5865       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5866       size--;
5867
5868       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5869       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5870
5871
5872     }
5873
5874     pic16_emitpLabel(lbl->key);
5875
5876     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5877     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5878         (AOP_TYPE(result) == AOP_REG)) {
5879       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5880       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5881     } else {
5882       genSkipc(&rFalseIfx);
5883     }         
5884     //genSkipc(&rFalseIfx);
5885     if(ifx) ifx->generated = 1;
5886
5887
5888             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5889               goto check_carry;
5890
5891     return;
5892
5893   }
5894
5895 check_carry:
5896   if ((AOP_TYPE(result) != AOP_CRY) 
5897         && AOP_SIZE(result)) {
5898     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5899
5900     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5901
5902     pic16_outBitC(result);
5903   } else {
5904     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5905     /* if the result is used in the next
5906        ifx conditional branch then generate
5907        code a little differently */
5908     if (ifx )
5909       genIfxJump (ifx,"c");
5910     else
5911       pic16_outBitC(result);
5912     /* leave the result in acc */
5913   }
5914
5915 }
5916
5917 #elif 0 /* VR version of genCmp() */    /* } else { */
5918
5919 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5920 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5921         operand *result, int offset, int invert_op)
5922 {
5923   /* add code here */
5924   
5925   /* check condition, > or < ?? */
5926   if(rIfx->condition != 0)invert_op ^= 1;
5927   
5928   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5929
5930   if(!ifx)invert_op ^= 1;
5931
5932   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5933       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5934   
5935   /* do selection */
5936   if(!invert_op)return POC_CPFSGT;
5937   else return POC_CPFSLT;
5938 }
5939
5940 static int compareAopfirstpass=1;
5941
5942 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5943             operand *oper, int offset, operand *result,
5944             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5945             symbol *tlbl)
5946 {
5947   int op;
5948   symbol *truelbl;
5949
5950   /* invert if there is a result to be loaded, in order to fit,
5951    * SETC/CLRC sequence */
5952   if(AOP_SIZE(result))invert_op ^= 1;
5953
5954 //  if(sign && !offset)invert_op ^= 1;
5955   
5956 //  if(sign)invert_op ^= 1;
5957   
5958   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5959
5960   if(AOP_SIZE(result) && compareAopfirstpass) {
5961     if(!ifx) {
5962       if(pcop2)
5963         pic16_emitpcode(POC_SETF, pcop2);
5964       else
5965         emitSETC;
5966     } else {
5967       if(pcop2)
5968         pic16_emitpcode(POC_CLRF, pcop2);
5969       else
5970         emitCLRC;
5971     }
5972   }
5973
5974   compareAopfirstpass = 0;
5975
5976       /* there is a bug when comparing operands with size > 1,
5977        * because higher bytes can be equal and test should be performed
5978        * to the next lower byte, current algorithm, considers operands
5979        * inequal in these cases! -- VR 20041107 */
5980
5981     
5982   if(pcop)
5983     pic16_emitpcode(op, pcop);
5984   else
5985     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5986
5987
5988   if((!sign || !offset) && AOP_SIZE(result)) {
5989     if(!ifx) {
5990       if(pcop2)
5991         pic16_emitpcode(POC_CLRF, pcop2);
5992         else
5993         emitCLRC;
5994     } else {
5995       if(pcop2)
5996         pic16_emitpcode(POC_SETF, pcop2);
5997       else
5998         emitSETC;
5999     }
6000     
6001     /* don't emit final branch (offset == 0) */
6002     if(offset) {
6003
6004       if(pcop2)
6005         pic16_emitpcode(POC_RRCF, pcop2);
6006
6007       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6008     }
6009   } else {
6010     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6011       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6012             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6013
6014       truelbl = newiTempLabel( NULL );
6015       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6016       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6017         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6018       else
6019         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6020       pic16_emitpLabel(truelbl->key);
6021     } else {
6022       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6023     }
6024   }
6025 }
6026
6027 static void genCmp (operand *left, operand *right,
6028                     operand *result, iCode *ifx, int sign)
6029 {
6030   int size, cmpop=1;
6031   long lit = 0L;
6032   resolvedIfx rFalseIfx;
6033   symbol *falselbl, *tlbl;
6034
6035     FENTRY;
6036     
6037     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6038
6039     resolveIfx(&rFalseIfx, ifx);
6040     size = max(AOP_SIZE(left), AOP_SIZE(right));
6041     
6042     /* if left & right are bit variables */
6043     if(AOP_TYPE(left) == AOP_CRY
6044       && AOP_TYPE(right) == AOP_CRY ) {
6045
6046         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6047         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6048         
6049         werror(W_POSSBUG2, __FILE__, __LINE__);
6050         exit(-1);
6051     }
6052     
6053     /* if literal is on the right then swap with left */
6054     if((AOP_TYPE(right) == AOP_LIT)) {
6055       operand *tmp = right ;
6056 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
6057
6058         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6059
6060 //      lit = (lit - 1) & mask;
6061         right = left;
6062         left = tmp;
6063         rFalseIfx.condition ^= 1;               /* reverse compare */
6064     } else
6065     if ((AOP_TYPE(left) == AOP_LIT)) {
6066       /* float compares are handled by support functions */
6067       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6068     }
6069
6070     /* actual comparing algorithm */
6071 //    size = AOP_SIZE( right );
6072
6073     falselbl = newiTempLabel( NULL );
6074     if(AOP_TYPE(left) == AOP_LIT) {
6075       /* compare to literal */
6076       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6077       
6078       if(sign) {
6079         pCodeOp *pct, *pct2;
6080         symbol *tlbl1;
6081
6082         /* signed compare */
6083         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6084
6085         pct = pic16_popCopyReg(&pic16_pc_prodl);
6086         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6087         tlbl = newiTempLabel( NULL );
6088         
6089         /* first compare signs:
6090          *  a. if both are positive, compare just like unsigned
6091          *  b. if both are negative, invert cmpop, compare just like unsigned
6092          *  c. if different signs, determine the result directly */
6093
6094         size--;
6095
6096 #if 1
6097         /* { */
6098         tlbl1 = newiTempLabel( NULL );
6099 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6100
6101         if(lit > 0) {
6102
6103           /* literal is zero or positive:
6104            *  a. if carry is zero, too, continue compare,
6105            *  b. if carry is set, then continue depending on cmpop ^ condition:
6106            *    1. '<' return false (literal < variable),
6107            *    2. '>' return true (literal > variable) */
6108 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6109           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6110           
6111           
6112           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6113           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6114         } else 
6115         if(lit < 0) {
6116           
6117           /* literal is negative:
6118            *  a. if carry is set, too, continue compare,
6119            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6120            *    1. '<' return true (literal < variable),
6121            *    2. '>' return false (literal > variable) */
6122 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6123           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6124           
6125           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6126           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6127         }
6128 #if 1
6129         else {
6130           /* lit == 0 */
6131           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6132           
6133           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6134           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6135         }
6136 #endif
6137         
6138         
6139         pic16_emitpLabel( tlbl1->key );
6140 #endif  /* } */
6141
6142         compareAopfirstpass=1;
6143 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6144 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6145 //        pic16_emitpcode(POC_MOVWF, pct);
6146
6147 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6148         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6149 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6150         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6151
6152         /* generic case */        
6153           while( size-- ) {
6154 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6155 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6156 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6157 //            pic16_emitpcode(POC_MOVWF, pct);
6158
6159 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6160             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6161             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6162 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6163 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6164           }
6165         
6166         if(ifx)ifx->generated = 1;
6167
6168         if(AOP_SIZE(result)) {
6169           pic16_emitpLabel(tlbl->key);
6170           pic16_emitpLabel(falselbl->key);
6171           pic16_outBitOp( result, pct2 );
6172         } else {
6173           pic16_emitpLabel(tlbl->key);
6174         }
6175       } else {
6176
6177         /* unsigned compare */      
6178         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6179     
6180         compareAopfirstpass=1;
6181         while(size--) {
6182           
6183           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6184           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6185
6186         }
6187         if(ifx)ifx->generated = 1;
6188
6189         if(AOP_SIZE(result)) {
6190           pic16_emitpLabel(falselbl->key);
6191           pic16_outBitC( result );
6192         }
6193
6194       }
6195     } else {
6196       /* compare registers */
6197       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6198
6199
6200       if(sign) {
6201         pCodeOp *pct, *pct2;
6202         
6203         /* signed compare */
6204         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6205
6206         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6207         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6208         tlbl = newiTempLabel( NULL );
6209         
6210         compareAopfirstpass=1;
6211
6212         size--;
6213         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6214 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6215         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6216         pic16_emitpcode(POC_MOVWF, pct);
6217
6218         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6219 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6220         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6221
6222         /* WREG already holds left + 0x80 */
6223         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6224         
6225         while( size-- ) {
6226           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6227 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6228           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6229           pic16_emitpcode(POC_MOVWF, pct);
6230                 
6231           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6232 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6233           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6234
6235           /* WREG already holds left + 0x80 */
6236           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6237 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6238         }
6239         
6240         if(ifx)ifx->generated = 1;
6241
6242         if(AOP_SIZE(result)) {
6243           pic16_emitpLabel(tlbl->key);
6244           pic16_emitpLabel(falselbl->key);
6245           pic16_outBitOp( result, pct2 );
6246         } else {
6247           pic16_emitpLabel(tlbl->key);
6248         }
6249
6250       } else {
6251         /* unsigned compare */      
6252         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6253
6254         compareAopfirstpass=1;
6255         while(size--) {
6256           
6257           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6258           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6259
6260         }
6261
6262         if(ifx)ifx->generated = 1;
6263         if(AOP_SIZE(result)) {
6264
6265           pic16_emitpLabel(falselbl->key);
6266           pic16_outBitC( result );
6267         }
6268
6269       }
6270     }
6271 }
6272
6273 #endif  /* } */
6274
6275
6276
6277 /*-----------------------------------------------------------------*/
6278 /* genCmpGt :- greater than comparison                             */
6279 /*-----------------------------------------------------------------*/
6280 static void genCmpGt (iCode *ic, iCode *ifx)
6281 {
6282   operand *left, *right, *result;
6283   sym_link *letype , *retype;
6284   int sign ;
6285
6286     FENTRY;
6287     
6288     left = IC_LEFT(ic);
6289     right= IC_RIGHT(ic);
6290     result = IC_RESULT(ic);
6291
6292     letype = getSpec(operandType(left));
6293     retype =getSpec(operandType(right));
6294     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6295     /* assign the amsops */
6296     pic16_aopOp (left,ic,FALSE);
6297     pic16_aopOp (right,ic,FALSE);
6298     pic16_aopOp (result,ic,TRUE);
6299
6300     genCmp(right, left, result, ifx, sign);
6301
6302     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6303     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6304     pic16_freeAsmop(result,NULL,ic,TRUE); 
6305 }
6306
6307 /*-----------------------------------------------------------------*/
6308 /* genCmpLt - less than comparisons                                */
6309 /*-----------------------------------------------------------------*/
6310 static void genCmpLt (iCode *ic, iCode *ifx)
6311 {
6312   operand *left, *right, *result;
6313   sym_link *letype , *retype;
6314   int sign ;
6315
6316     FENTRY;
6317
6318     left = IC_LEFT(ic);
6319     right= IC_RIGHT(ic);
6320     result = IC_RESULT(ic);
6321
6322     letype = getSpec(operandType(left));
6323     retype =getSpec(operandType(right));
6324     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6325
6326     /* assign the amsops */
6327     pic16_aopOp (left,ic,FALSE);
6328     pic16_aopOp (right,ic,FALSE);
6329     pic16_aopOp (result,ic,TRUE);
6330
6331     genCmp(left, right, result, ifx, sign);
6332
6333     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6334     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6335     pic16_freeAsmop(result,NULL,ic,TRUE); 
6336 }
6337
6338 #if 0
6339 // not needed ATM
6340 // FIXME reenable literal optimisation when the pic16 port is stable
6341
6342 /*-----------------------------------------------------------------*/
6343 /* genc16bit2lit - compare a 16 bit value to a literal             */
6344 /*-----------------------------------------------------------------*/
6345 static void genc16bit2lit(operand *op, int lit, int offset)
6346 {
6347   int i;
6348
6349   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6350   if( (lit&0xff) == 0) 
6351     i=1;
6352   else
6353     i=0;
6354
6355   switch( BYTEofLONG(lit,i)) { 
6356   case 0:
6357     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6358     break;
6359   case 1:
6360     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6361     break;
6362   case 0xff:
6363     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6364     break;
6365   default:
6366     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6367     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6368   }
6369
6370   i ^= 1;
6371
6372   switch( BYTEofLONG(lit,i)) { 
6373   case 0:
6374     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6375     break;
6376   case 1:
6377     emitSKPNZ;
6378     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6379     break;
6380   case 0xff:
6381     emitSKPNZ;
6382     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6383     break;
6384   default:
6385     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6386     emitSKPNZ;
6387     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6388
6389   }
6390
6391 }
6392 #endif
6393
6394 #if 0
6395 // not needed ATM
6396 /*-----------------------------------------------------------------*/
6397 /* gencjneshort - compare and jump if not equal                    */
6398 /*-----------------------------------------------------------------*/
6399 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6400 {
6401   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6402   int offset = 0;
6403   int res_offset = 0;  /* the result may be a different size then left or right */
6404   int res_size = AOP_SIZE(result);
6405   resolvedIfx rIfx;
6406   symbol *lbl, *lbl_done;
6407
6408   unsigned long lit = 0L;
6409   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6410
6411   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6412   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6413   if(result)
6414     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6415   resolveIfx(&rIfx,ifx);
6416   lbl =  newiTempLabel(NULL);
6417   lbl_done =  newiTempLabel(NULL);
6418
6419
6420   /* if the left side is a literal or 
6421      if the right is in a pointer register and left 
6422      is not */
6423   if ((AOP_TYPE(left) == AOP_LIT) || 
6424       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6425     operand *t = right;
6426     right = left;
6427     left = t;
6428   }
6429   if(AOP_TYPE(right) == AOP_LIT)
6430     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6431
6432   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6433     preserve_result = 1;
6434
6435   if(result && !preserve_result)
6436     {
6437       int i;
6438       for(i = 0; i < AOP_SIZE(result); i++)
6439         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6440     }
6441
6442
6443   /* if the right side is a literal then anything goes */
6444   if (AOP_TYPE(right) == AOP_LIT &&
6445       AOP_TYPE(left) != AOP_DIR ) {
6446     switch(size) {
6447     case 2:
6448       genc16bit2lit(left, lit, 0);
6449       emitSKPZ;
6450       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6451       break;
6452     default:
6453       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6454       while (size--) {
6455         if(lit & 0xff) {
6456           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6457           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6458         } else {
6459           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6460         }
6461
6462         emitSKPZ;
6463         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6464         offset++;
6465         if(res_offset < res_size-1)
6466           res_offset++;
6467         lit >>= 8;
6468       }
6469       break;
6470     }
6471   }
6472
6473   /* if the right side is in a register or in direct space or
6474      if the left is a pointer register & right is not */    
6475   else if (AOP_TYPE(right) == AOP_REG ||
6476            AOP_TYPE(right) == AOP_DIR || 
6477            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6478            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6479     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6480     int lbl_key = lbl->key;
6481
6482     if(result) {
6483       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6484       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6485     }else {
6486       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6487       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6488               __FUNCTION__,__LINE__);
6489       return;
6490     }
6491    
6492 /*     switch(size) { */
6493 /*     case 2: */
6494 /*       genc16bit2lit(left, lit, 0); */
6495 /*       emitSKPNZ; */
6496 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6497 /*       break; */
6498 /*     default: */
6499     while (size--) {
6500       int emit_skip=1;
6501       if((AOP_TYPE(left) == AOP_DIR) && 
6502          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6503
6504         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6505         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6506
6507       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6508             
6509         switch (lit & 0xff) {
6510         case 0:
6511           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6512           break;
6513         case 1:
6514           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6515           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6516           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6517           emit_skip=0;
6518           break;
6519         case 0xff:
6520           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6521           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6522           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6523           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6524           emit_skip=0;
6525           break;
6526         default:
6527           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6528           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6529         }
6530         lit >>= 8;
6531
6532       } else {
6533         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6534       }
6535       if(emit_skip) {
6536         if(AOP_TYPE(result) == AOP_CRY) {
6537           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6538           if(rIfx.condition)
6539             emitSKPNZ;
6540           else
6541             emitSKPZ;
6542           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6543         } else {
6544           /* fix me. probably need to check result size too */
6545           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6546           if(rIfx.condition)
6547             emitSKPZ;
6548           else
6549             emitSKPNZ;
6550           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6551           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6552         }
6553         if(ifx)
6554           ifx->generated=1;
6555       }
6556       emit_skip++;
6557       offset++;
6558       if(res_offset < res_size-1)
6559         res_offset++;
6560     }
6561 /*       break; */
6562 /*     } */
6563   } else if(AOP_TYPE(right) == AOP_REG &&
6564             AOP_TYPE(left) != AOP_DIR){
6565
6566     while(size--) {
6567       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6568       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6569       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6570       if(rIfx.condition)
6571         emitSKPNZ;
6572       else
6573         emitSKPZ;
6574       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6575       offset++;
6576       if(res_offset < res_size-1)
6577         res_offset++;
6578     }
6579       
6580   }else{
6581     /* right is a pointer reg need both a & b */
6582     while(size--) {
6583       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6584       if(strcmp(l,"b"))
6585         pic16_emitcode("mov","b,%s",l);
6586       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6587       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6588       offset++;
6589     }
6590   }
6591
6592   if(result && preserve_result)
6593     {
6594       int i;
6595       for(i = 0; i < AOP_SIZE(result); i++)
6596         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6597     }
6598
6599   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6600
6601   if(result && preserve_result)
6602     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6603
6604   if(!rIfx.condition)
6605     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6606
6607   pic16_emitpLabel(lbl->key);
6608
6609   if(result && preserve_result)
6610     {
6611       int i;
6612       for(i = 0; i < AOP_SIZE(result); i++)
6613         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6614
6615       pic16_emitpLabel(lbl_done->key);
6616    }
6617
6618   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6619
6620   if(ifx)
6621     ifx->generated = 1;
6622 }
6623 #endif
6624
6625 #if 0
6626 /*-----------------------------------------------------------------*/
6627 /* gencjne - compare and jump if not equal                         */
6628 /*-----------------------------------------------------------------*/
6629 static void gencjne(operand *left, operand *right, iCode *ifx)
6630 {
6631     symbol *tlbl  = newiTempLabel(NULL);
6632
6633     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6634     gencjneshort(left, right, lbl);
6635
6636     pic16_emitcode("mov","a,%s",one);
6637     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6638     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6639     pic16_emitcode("clr","a");
6640     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6641
6642     pic16_emitpLabel(lbl->key);
6643     pic16_emitpLabel(tlbl->key);
6644
6645 }
6646 #endif
6647
6648
6649 /*-----------------------------------------------------------------*/
6650 /* is_LitOp - check if operand has to be treated as literal        */
6651 /*-----------------------------------------------------------------*/
6652 static bool is_LitOp(operand *op)
6653 {
6654   return ((AOP_TYPE(op) == AOP_LIT)
6655       || ( (AOP_TYPE(op) == AOP_PCODE)
6656           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6657               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6658 }
6659
6660 /*-----------------------------------------------------------------*/
6661 /* is_LitAOp - check if operand has to be treated as literal        */
6662 /*-----------------------------------------------------------------*/
6663 static bool is_LitAOp(asmop *aop)
6664 {
6665   return ((aop->type == AOP_LIT)
6666       || ( (aop->type == AOP_PCODE)
6667           && ( (aop->aopu.pcop->type == PO_LITERAL)
6668               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6669 }
6670
6671
6672
6673 /*-----------------------------------------------------------------*/
6674 /* genCmpEq - generates code for equal to                          */
6675 /*-----------------------------------------------------------------*/
6676 static void genCmpEq (iCode *ic, iCode *ifx)
6677 {
6678   operand *left, *right, *result;
6679   symbol *falselbl = newiTempLabel(NULL);
6680   symbol *donelbl = newiTempLabel(NULL);
6681
6682   int preserve_result = 0;
6683   int generate_result = 0;
6684   int i=0;
6685   unsigned long lit = -1;
6686
6687   FENTRY;
6688   
6689   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6690   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6691   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6692  
6693   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6694
6695   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6696     {
6697       werror(W_POSSBUG2, __FILE__, __LINE__);
6698       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6699       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6700       goto release;
6701     }
6702
6703   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6704     {
6705       operand *tmp = right ;
6706       right = left;
6707       left = tmp;
6708     }
6709
6710   if (AOP_TYPE(right) == AOP_LIT) {
6711     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6712   }
6713
6714   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6715     preserve_result = 1;
6716
6717   if(result && AOP_SIZE(result))
6718     generate_result = 1;
6719
6720   if(generate_result && !preserve_result)
6721     {
6722       for(i = 0; i < AOP_SIZE(result); i++)
6723         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6724     }
6725
6726   for(i=0; i < AOP_SIZE(left); i++)
6727     {
6728       if(AOP_TYPE(left) != AOP_ACC)
6729         {
6730           if(is_LitOp(left))
6731             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6732           else
6733             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6734         }
6735       if(is_LitOp(right)) {
6736         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6737           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6738         }
6739       } else
6740         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6741
6742       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6743     }
6744
6745   // result == true
6746
6747   if(generate_result && preserve_result)
6748     {
6749       for(i = 0; i < AOP_SIZE(result); i++)
6750         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6751     }
6752
6753   if(generate_result)
6754     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6755
6756   if(generate_result && preserve_result)
6757     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6758
6759   if(ifx && IC_TRUE(ifx))
6760     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6761
6762   if(ifx && IC_FALSE(ifx))
6763     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6764
6765   pic16_emitpLabel(falselbl->key);
6766
6767   // result == false
6768
6769   if(ifx && IC_FALSE(ifx))
6770     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6771
6772   if(generate_result && preserve_result)
6773     {
6774       for(i = 0; i < AOP_SIZE(result); i++)
6775         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6776     }
6777
6778   pic16_emitpLabel(donelbl->key);
6779
6780   if(ifx)
6781     ifx->generated = 1;
6782
6783 release:
6784   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6785   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6786   pic16_freeAsmop(result,NULL,ic,TRUE);
6787
6788 }
6789
6790
6791 #if 0
6792 // old version kept for reference
6793
6794 /*-----------------------------------------------------------------*/
6795 /* genCmpEq - generates code for equal to                          */
6796 /*-----------------------------------------------------------------*/
6797 static void genCmpEq (iCode *ic, iCode *ifx)
6798 {
6799     operand *left, *right, *result;
6800     unsigned long lit = 0L;
6801     int size,offset=0;
6802     symbol *falselbl  = newiTempLabel(NULL);
6803
6804
6805     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6806
6807     if(ifx)
6808       DEBUGpic16_emitcode ("; ifx is non-null","");
6809     else
6810       DEBUGpic16_emitcode ("; ifx is null","");
6811
6812     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6813     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6814     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6815
6816     size = max(AOP_SIZE(left),AOP_SIZE(right));
6817
6818     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6819
6820     /* if literal, literal on the right or 
6821     if the right is in a pointer register and left 
6822     is not */
6823     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6824         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6825       operand *tmp = right ;
6826       right = left;
6827       left = tmp;
6828     }
6829
6830
6831     if(ifx && !AOP_SIZE(result)){
6832         symbol *tlbl;
6833         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6834         /* if they are both bit variables */
6835         if (AOP_TYPE(left) == AOP_CRY &&
6836             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6837                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6838             if(AOP_TYPE(right) == AOP_LIT){
6839                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6840                 if(lit == 0L){
6841                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6842                     pic16_emitcode("cpl","c");
6843                 } else if(lit == 1L) {
6844                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6845                 } else {
6846                     pic16_emitcode("clr","c");
6847                 }
6848                 /* AOP_TYPE(right) == AOP_CRY */
6849             } else {
6850                 symbol *lbl = newiTempLabel(NULL);
6851                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6852                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6853                 pic16_emitcode("cpl","c");
6854                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6855             }
6856             /* if true label then we jump if condition
6857             supplied is true */
6858             tlbl = newiTempLabel(NULL);
6859             if ( IC_TRUE(ifx) ) {
6860                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6861                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6862             } else {
6863                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6864                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6865             }
6866             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6867
6868                 {
6869                 /* left and right are both bit variables, result is carry */
6870                         resolvedIfx rIfx;
6871               
6872                         resolveIfx(&rIfx,ifx);
6873
6874                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6875                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6876                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6877                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6878                         genSkipz2(&rIfx,0);
6879                 }
6880         } else {
6881
6882                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6883
6884                         /* They're not both bit variables. Is the right a literal? */
6885                         if(AOP_TYPE(right) == AOP_LIT) {
6886                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6887             
6888                         switch(size) {
6889
6890                                 case 1:
6891                                         switch(lit & 0xff) {
6892                                                 case 1:
6893                                                                 if ( IC_TRUE(ifx) ) {
6894                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6895                                                                         emitSKPNZ;
6896                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6897                                                                 } else {
6898                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6899                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6900                                                                 }
6901                                                                 break;
6902                                                 case 0xff:
6903                                                                 if ( IC_TRUE(ifx) ) {
6904                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6905                                                                         emitSKPNZ;
6906                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6907                                                                 } else {
6908                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6909                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6910                                                                 }
6911                                                                 break;
6912                                                 default:
6913                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6914                                                                 if(lit)
6915                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6916                                                                 genSkip(ifx,'z');
6917                                         } // switch lit
6918
6919
6920                                         /* end of size == 1 */
6921                                         break;
6922               
6923                                 case 2:
6924                                         genc16bit2lit(left,lit,offset);
6925                                         genSkip(ifx,'z');
6926                                         break;
6927                                         /* end of size == 2 */
6928
6929                                 default:
6930                                         /* size is 4 */
6931                                         if(lit==0) {
6932                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6933                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6934                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6935                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6936                                                 genSkip(ifx,'z');
6937                                         } else {
6938                                                 /* search for patterns that can be optimized */
6939
6940                                                 genc16bit2lit(left,lit,0);
6941                                                 lit >>= 16;
6942                                                 if(lit) {
6943                                                                 if(IC_TRUE(ifx))
6944                                                                 emitSKPZ; // if hi word unequal
6945                                                                 else
6946                                                                 emitSKPNZ; // if hi word equal
6947                                                                 // fail early
6948                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6949                                                         genc16bit2lit(left,lit,2);
6950                                                         genSkip(ifx,'z');
6951                                                 } else {
6952                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6953                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6954                                                         genSkip(ifx,'z');
6955                                                 }
6956                                         }
6957                                                 pic16_emitpLabel(falselbl->key);
6958                                                 break;
6959
6960                         } // switch size
6961           
6962                         ifx->generated = 1;
6963                         goto release ;
6964             
6965
6966           } else if(AOP_TYPE(right) == AOP_CRY ) {
6967             /* we know the left is not a bit, but that the right is */
6968             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6969             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6970                       pic16_popGet(AOP(right),offset));
6971             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6972
6973             /* if the two are equal, then W will be 0 and the Z bit is set
6974              * we could test Z now, or go ahead and check the high order bytes if
6975              * the variable we're comparing is larger than a byte. */
6976
6977             while(--size)
6978               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6979
6980             if ( IC_TRUE(ifx) ) {
6981               emitSKPNZ;
6982               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6983               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6984             } else {
6985               emitSKPZ;
6986               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6987               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6988             }
6989
6990           } else {
6991             /* They're both variables that are larger than bits */
6992             int s = size;
6993
6994             tlbl = newiTempLabel(NULL);
6995
6996             while(size--) {
6997               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6998               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6999
7000               if ( IC_TRUE(ifx) ) {
7001                 if(size) {
7002                   emitSKPZ;
7003                 
7004                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7005
7006                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7007                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7008                 } else {
7009                   emitSKPNZ;
7010
7011                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7012
7013
7014                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7015                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7016                 }
7017               } else {
7018                 emitSKPZ;
7019
7020                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7021
7022                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7023                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7024               }
7025               offset++;
7026             }
7027             if(s>1 && IC_TRUE(ifx)) {
7028               pic16_emitpLabel(tlbl->key);
7029               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7030             }
7031           }
7032         }
7033         /* mark the icode as generated */
7034         ifx->generated = 1;
7035         goto release ;
7036     }
7037
7038     /* if they are both bit variables */
7039     if (AOP_TYPE(left) == AOP_CRY &&
7040         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7041         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7042         if(AOP_TYPE(right) == AOP_LIT){
7043             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7044             if(lit == 0L){
7045                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7046                 pic16_emitcode("cpl","c");
7047             } else if(lit == 1L) {
7048                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7049             } else {
7050                 pic16_emitcode("clr","c");
7051             }
7052             /* AOP_TYPE(right) == AOP_CRY */
7053         } else {
7054             symbol *lbl = newiTempLabel(NULL);
7055             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7056             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7057             pic16_emitcode("cpl","c");
7058             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7059         }
7060         /* c = 1 if egal */
7061         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7062             pic16_outBitC(result);
7063             goto release ;
7064         }
7065         if (ifx) {
7066             genIfxJump (ifx,"c");
7067             goto release ;
7068         }
7069         /* if the result is used in an arithmetic operation
7070         then put the result in place */
7071         pic16_outBitC(result);
7072     } else {
7073       
7074       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7075       gencjne(left,right,result,ifx);
7076 /*
7077       if(ifx) 
7078         gencjne(left,right,newiTempLabel(NULL));
7079       else {
7080         if(IC_TRUE(ifx)->key)
7081           gencjne(left,right,IC_TRUE(ifx)->key);
7082         else
7083           gencjne(left,right,IC_FALSE(ifx)->key);
7084         ifx->generated = 1;
7085         goto release ;
7086       }
7087       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7088         pic16_aopPut(AOP(result),"a",0);
7089         goto release ;
7090       }
7091
7092       if (ifx) {
7093         genIfxJump (ifx,"a");
7094         goto release ;
7095       }
7096 */
7097       /* if the result is used in an arithmetic operation
7098          then put the result in place */
7099 /*
7100       if (AOP_TYPE(result) != AOP_CRY) 
7101         pic16_outAcc(result);
7102 */
7103       /* leave the result in acc */
7104     }
7105
7106 release:
7107     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7108     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7109     pic16_freeAsmop(result,NULL,ic,TRUE);
7110 }
7111 #endif
7112
7113 /*-----------------------------------------------------------------*/
7114 /* ifxForOp - returns the icode containing the ifx for operand     */
7115 /*-----------------------------------------------------------------*/
7116 static iCode *ifxForOp ( operand *op, iCode *ic )
7117 {
7118   FENTRY2;
7119
7120     /* if true symbol then needs to be assigned */
7121     if (IS_TRUE_SYMOP(op))
7122         return NULL ;
7123
7124     /* if this has register type condition and
7125     the next instruction is ifx with the same operand
7126     and live to of the operand is upto the ifx only then */
7127     if (ic->next
7128         && ic->next->op == IFX
7129         && IC_COND(ic->next)->key == op->key
7130         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7131         ) {
7132                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7133           return ic->next;
7134     }
7135
7136     /*
7137     if (ic->next &&
7138         ic->next->op == IFX &&
7139         IC_COND(ic->next)->key == op->key) {
7140       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7141       return ic->next;
7142     }
7143     */
7144
7145     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7146     if (ic->next &&
7147         ic->next->op == IFX)
7148       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7149
7150     if (ic->next &&
7151         ic->next->op == IFX &&
7152         IC_COND(ic->next)->key == op->key) {
7153       DEBUGpic16_emitcode ("; "," key is okay");
7154       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7155                            OP_SYMBOL(op)->liveTo,
7156                            ic->next->seq);
7157     }
7158
7159 #if 0
7160     /* the code below is completely untested
7161      * it just allows ulong2fs.c compile -- VR */
7162          
7163     ic = ic->next;
7164     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7165                                         __FILE__, __FUNCTION__, __LINE__);
7166         
7167     /* if this has register type condition and
7168     the next instruction is ifx with the same operand
7169     and live to of the operand is upto the ifx only then */
7170     if (ic->next &&
7171         ic->next->op == IFX &&
7172         IC_COND(ic->next)->key == op->key &&
7173         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7174         return ic->next;
7175
7176     if (ic->next &&
7177         ic->next->op == IFX &&
7178         IC_COND(ic->next)->key == op->key) {
7179       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7180       return ic->next;
7181     }
7182
7183     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7184                                         __FILE__, __FUNCTION__, __LINE__);
7185
7186 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7187 #endif
7188
7189     return NULL;
7190 }
7191 /*-----------------------------------------------------------------*/
7192 /* genAndOp - for && operation                                     */
7193 /*-----------------------------------------------------------------*/
7194 static void genAndOp (iCode *ic)
7195 {
7196   operand *left,*right, *result;
7197 /*     symbol *tlbl; */
7198
7199     FENTRY;
7200
7201     /* note here that && operations that are in an
7202     if statement are taken away by backPatchLabels
7203     only those used in arthmetic operations remain */
7204     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7205     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7206     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7207
7208     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7209
7210     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7211     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7212     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7213
7214     /* if both are bit variables */
7215 /*     if (AOP_TYPE(left) == AOP_CRY && */
7216 /*         AOP_TYPE(right) == AOP_CRY ) { */
7217 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7218 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7219 /*         pic16_outBitC(result); */
7220 /*     } else { */
7221 /*         tlbl = newiTempLabel(NULL); */
7222 /*         pic16_toBoolean(left);     */
7223 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7224 /*         pic16_toBoolean(right); */
7225 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7226 /*         pic16_outBitAcc(result); */
7227 /*     } */
7228
7229     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7230     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7231     pic16_freeAsmop(result,NULL,ic,TRUE);
7232 }
7233
7234
7235 /*-----------------------------------------------------------------*/
7236 /* genOrOp - for || operation                                      */
7237 /*-----------------------------------------------------------------*/
7238 /*
7239   tsd pic port -
7240   modified this code, but it doesn't appear to ever get called
7241 */
7242
7243 static void genOrOp (iCode *ic)
7244 {
7245   operand *left,*right, *result;
7246   symbol *tlbl;
7247
7248     FENTRY;  
7249
7250   /* note here that || operations that are in an
7251     if statement are taken away by backPatchLabels
7252     only those used in arthmetic operations remain */
7253     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7254     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7255     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7256
7257     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7258
7259     /* if both are bit variables */
7260     if (AOP_TYPE(left) == AOP_CRY &&
7261         AOP_TYPE(right) == AOP_CRY ) {
7262       pic16_emitcode("clrc","");
7263       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7264                AOP(left)->aopu.aop_dir,
7265                AOP(left)->aopu.aop_dir);
7266       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7267                AOP(right)->aopu.aop_dir,
7268                AOP(right)->aopu.aop_dir);
7269       pic16_emitcode("setc","");
7270
7271     } else {
7272         tlbl = newiTempLabel(NULL);
7273         pic16_toBoolean(left);
7274         emitSKPZ;
7275         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7276         pic16_toBoolean(right);
7277         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7278
7279         pic16_outBitAcc(result);
7280     }
7281
7282     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7283     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7284     pic16_freeAsmop(result,NULL,ic,TRUE);            
7285 }
7286
7287 /*-----------------------------------------------------------------*/
7288 /* isLiteralBit - test if lit == 2^n                               */
7289 /*-----------------------------------------------------------------*/
7290 static int isLiteralBit(unsigned long lit)
7291 {
7292     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7293     0x100L,0x200L,0x400L,0x800L,
7294     0x1000L,0x2000L,0x4000L,0x8000L,
7295     0x10000L,0x20000L,0x40000L,0x80000L,
7296     0x100000L,0x200000L,0x400000L,0x800000L,
7297     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7298     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7299     int idx;
7300     
7301     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7302     for(idx = 0; idx < 32; idx++)
7303         if(lit == pw[idx])
7304             return idx+1;
7305     return 0;
7306 }
7307
7308 /*-----------------------------------------------------------------*/
7309 /* continueIfTrue -                                                */
7310 /*-----------------------------------------------------------------*/
7311 static void continueIfTrue (iCode *ic)
7312 {
7313   FENTRY;
7314   if(IC_TRUE(ic))
7315     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7316   ic->generated = 1;
7317 }
7318
7319 /*-----------------------------------------------------------------*/
7320 /* jmpIfTrue -                                                     */
7321 /*-----------------------------------------------------------------*/
7322 static void jumpIfTrue (iCode *ic)
7323 {
7324   FENTRY;
7325   if(!IC_TRUE(ic))
7326     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7327   ic->generated = 1;
7328 }
7329
7330 /*-----------------------------------------------------------------*/
7331 /* jmpTrueOrFalse -                                                */
7332 /*-----------------------------------------------------------------*/
7333 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7334 {
7335   // ugly but optimized by peephole
7336   FENTRY;
7337   if(IC_TRUE(ic)){
7338     symbol *nlbl = newiTempLabel(NULL);
7339       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7340       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7341       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7342       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7343   } else {
7344     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7345     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7346   }
7347   ic->generated = 1;
7348 }
7349
7350 /*-----------------------------------------------------------------*/
7351 /* genAnd  - code for and                                          */
7352 /*-----------------------------------------------------------------*/
7353 static void genAnd (iCode *ic, iCode *ifx)
7354 {
7355   operand *left, *right, *result;
7356   int size, offset=0;  
7357   unsigned long lit = 0L;
7358   int bytelit = 0;
7359   resolvedIfx rIfx;
7360
7361     FENTRY;
7362     
7363   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7364   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7365   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7366
7367   resolveIfx(&rIfx,ifx);
7368
7369   /* if left is a literal & right is not then exchange them */
7370   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7371       AOP_NEEDSACC(left)) {
7372     operand *tmp = right ;
7373     right = left;
7374     left = tmp;
7375   }
7376
7377   /* if result = right then exchange them */
7378   if(pic16_sameRegs(AOP(result),AOP(right))){
7379     operand *tmp = right ;
7380     right = left;
7381     left = tmp;
7382   }
7383
7384   /* if right is bit then exchange them */
7385   if (AOP_TYPE(right) == AOP_CRY &&
7386       AOP_TYPE(left) != AOP_CRY){
7387     operand *tmp = right ;
7388     right = left;
7389     left = tmp;
7390   }
7391   if(AOP_TYPE(right) == AOP_LIT)
7392     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7393
7394   size = AOP_SIZE(result);
7395
7396   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7397
7398   // if(bit & yy)
7399   // result = bit & yy;
7400   if (AOP_TYPE(left) == AOP_CRY){
7401     // c = bit & literal;
7402     if(AOP_TYPE(right) == AOP_LIT){
7403       if(lit & 1) {
7404         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7405           // no change
7406           goto release;
7407         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7408       } else {
7409         // bit(result) = 0;
7410         if(size && (AOP_TYPE(result) == AOP_CRY)){
7411           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7412           goto release;
7413         }
7414         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7415           jumpIfTrue(ifx);
7416           goto release;
7417         }
7418         pic16_emitcode("clr","c");
7419       }
7420     } else {
7421       if (AOP_TYPE(right) == AOP_CRY){
7422         // c = bit & bit;
7423         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7424         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7425       } else {
7426         // c = bit & val;
7427         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7428         // c = lsb
7429         pic16_emitcode("rrc","a");
7430         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7431       }
7432     }
7433     // bit = c
7434     // val = c
7435     if(size)
7436       pic16_outBitC(result);
7437     // if(bit & ...)
7438     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7439       genIfxJump(ifx, "c");           
7440     goto release ;
7441   }
7442
7443   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7444   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7445   if((AOP_TYPE(right) == AOP_LIT) &&
7446      (AOP_TYPE(result) == AOP_CRY) &&
7447      (AOP_TYPE(left) != AOP_CRY)){
7448     int posbit = isLiteralBit(lit);
7449     /* left &  2^n */
7450     if(posbit){
7451       posbit--;
7452       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7453       // bit = left & 2^n
7454       if(size)
7455         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7456       // if(left &  2^n)
7457       else{
7458         if(ifx){
7459 /*
7460           if(IC_TRUE(ifx)) {
7461             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7462             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7463           } else {
7464             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7465             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7466           }
7467 */
7468         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7469         size = AOP_SIZE(left);
7470
7471         {
7472           int bp = posbit, ofs=0;
7473           
7474             while(bp > 7) {
7475               bp -= 8;
7476               ofs++;
7477             }
7478
7479           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7480                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7481
7482         }
7483 /*
7484           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7485                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7486 */
7487           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7488           
7489           ifx->generated = 1;
7490         }
7491         goto release;
7492       }
7493     } else {
7494       symbol *tlbl = newiTempLabel(NULL);
7495       int sizel = AOP_SIZE(left);
7496
7497       if(size)
7498         emitSETC;
7499
7500       while(sizel--) {
7501         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7502
7503           /* patch provided by Aaron Colwell */
7504           if((posbit = isLiteralBit(bytelit)) != 0) {
7505               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7506                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7507                                                 (posbit-1),0, PO_GPR_REGISTER));
7508
7509               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7510 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7511           } else {
7512               if (bytelit == 0xff) {
7513                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7514                    * a peephole could optimize it out -- VR */
7515                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7516               } else {
7517                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7518                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7519               }
7520
7521               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7522                             pic16_popGetLabel(tlbl->key));
7523           }
7524         
7525 #if 0
7526           /* old code, left here for reference -- VR 09/2004 */
7527           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7528           // byte ==  2^n ?
7529           if((posbit = isLiteralBit(bytelit)) != 0)
7530             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7531           else{
7532             if(bytelit != 0x0FFL)
7533               pic16_emitcode("anl","a,%s",
7534                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7535             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7536           }
7537 #endif
7538         }
7539         offset++;
7540       }
7541       // bit = left & literal
7542       if(size) {
7543         emitCLRC;
7544         pic16_emitpLabel(tlbl->key);
7545       }
7546       // if(left & literal)
7547       else {
7548         if(ifx) {
7549           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7550           ifx->generated = 1;
7551         }
7552         pic16_emitpLabel(tlbl->key);
7553         goto release;
7554       }
7555     }
7556
7557     pic16_outBitC(result);
7558     goto release ;
7559   }
7560
7561   /* if left is same as result */
7562   if(pic16_sameRegs(AOP(result),AOP(left))){
7563     int know_W = -1;
7564     for(;size--; offset++,lit>>=8) {
7565       if(AOP_TYPE(right) == AOP_LIT){
7566         switch(lit & 0xff) {
7567         case 0x00:
7568           /*  and'ing with 0 has clears the result */
7569 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7570           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7571           break;
7572         case 0xff:
7573           /* and'ing with 0xff is a nop when the result and left are the same */
7574           break;
7575
7576         default:
7577           {
7578             int p = pic16_my_powof2( (~lit) & 0xff );
7579             if(p>=0) {
7580               /* only one bit is set in the literal, so use a bcf instruction */
7581 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7582               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7583
7584             } else {
7585               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7586               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7587               if(know_W != (lit&0xff))
7588                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7589               know_W = lit &0xff;
7590               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7591             }
7592           }    
7593         }
7594       } else {
7595         if (AOP_TYPE(left) == AOP_ACC) {
7596           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7597         } else {                    
7598           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7599           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7600
7601         }
7602       }
7603     }
7604
7605   } else {
7606     // left & result in different registers
7607     if(AOP_TYPE(result) == AOP_CRY){
7608       // result = bit
7609       // if(size), result in bit
7610       // if(!size && ifx), conditional oper: if(left & right)
7611       symbol *tlbl = newiTempLabel(NULL);
7612       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7613       if(size)
7614         pic16_emitcode("setb","c");
7615       while(sizer--){
7616         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7617         pic16_emitcode("anl","a,%s",
7618                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7619         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7620         offset++;
7621       }
7622       if(size){
7623         CLRC;
7624         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7625         pic16_outBitC(result);
7626       } else if(ifx)
7627         jmpTrueOrFalse(ifx, tlbl);
7628     } else {
7629       for(;(size--);offset++) {
7630         // normal case
7631         // result = left & right
7632         if(AOP_TYPE(right) == AOP_LIT){
7633           int t = (lit >> (offset*8)) & 0x0FFL;
7634           switch(t) { 
7635           case 0x00:
7636             pic16_emitcode("clrf","%s",
7637                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7638             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7639             break;
7640           case 0xff:
7641             pic16_emitcode("movf","%s,w",
7642                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7643             pic16_emitcode("movwf","%s",
7644                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7645             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7646             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7647             break;
7648           default:
7649             pic16_emitcode("movlw","0x%x",t);
7650             pic16_emitcode("andwf","%s,w",
7651                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7652             pic16_emitcode("movwf","%s",
7653                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7654               
7655             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7656             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7657             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7658           }
7659           continue;
7660         }
7661
7662         if (AOP_TYPE(left) == AOP_ACC) {
7663           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7664           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7665         } else {
7666           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7667           pic16_emitcode("andwf","%s,w",
7668                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7669           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7670           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7671         }
7672         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7673         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7674       }
7675     }
7676   }
7677
7678   release :
7679     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7680   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7681   pic16_freeAsmop(result,NULL,ic,TRUE);     
7682 }
7683
7684 /*-----------------------------------------------------------------*/
7685 /* genOr  - code for or                                            */
7686 /*-----------------------------------------------------------------*/
7687 static void genOr (iCode *ic, iCode *ifx)
7688 {
7689     operand *left, *right, *result;
7690     int size, offset=0;
7691     unsigned long lit = 0L;
7692
7693     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7694
7695     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7696     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7697     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7698
7699     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7700
7701     /* if left is a literal & right is not then exchange them */
7702     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7703         AOP_NEEDSACC(left)) {
7704         operand *tmp = right ;
7705         right = left;
7706         left = tmp;
7707     }
7708
7709     /* if result = right then exchange them */
7710     if(pic16_sameRegs(AOP(result),AOP(right))){
7711         operand *tmp = right ;
7712         right = left;
7713         left = tmp;
7714     }
7715
7716     /* if right is bit then exchange them */
7717     if (AOP_TYPE(right) == AOP_CRY &&
7718         AOP_TYPE(left) != AOP_CRY){
7719         operand *tmp = right ;
7720         right = left;
7721         left = tmp;
7722     }
7723
7724     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7725
7726     if(AOP_TYPE(right) == AOP_LIT)
7727         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7728
7729     size = AOP_SIZE(result);
7730
7731     // if(bit | yy)
7732     // xx = bit | yy;
7733     if (AOP_TYPE(left) == AOP_CRY){
7734         if(AOP_TYPE(right) == AOP_LIT){
7735             // c = bit & literal;
7736             if(lit){
7737                 // lit != 0 => result = 1
7738                 if(AOP_TYPE(result) == AOP_CRY){
7739                   if(size)
7740                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7741                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7742                   //     AOP(result)->aopu.aop_dir,
7743                   //     AOP(result)->aopu.aop_dir);
7744                     else if(ifx)
7745                         continueIfTrue(ifx);
7746                     goto release;
7747                 }
7748             } else {
7749                 // lit == 0 => result = left
7750                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7751                     goto release;
7752                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7753             }
7754         } else {
7755             if (AOP_TYPE(right) == AOP_CRY){
7756               if(pic16_sameRegs(AOP(result),AOP(left))){
7757                 // c = bit | bit;
7758                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7759                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7760                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7761
7762                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7763                          AOP(result)->aopu.aop_dir,
7764                          AOP(result)->aopu.aop_dir);
7765                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7766                          AOP(right)->aopu.aop_dir,
7767                          AOP(right)->aopu.aop_dir);
7768                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7769                          AOP(result)->aopu.aop_dir,
7770                          AOP(result)->aopu.aop_dir);
7771               } else {
7772                 if( AOP_TYPE(result) == AOP_ACC) {
7773                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7774                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7775                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7776                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7777
7778                 } else {
7779
7780                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7781                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7782                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7783                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7784
7785                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7786                                  AOP(result)->aopu.aop_dir,
7787                                  AOP(result)->aopu.aop_dir);
7788                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7789                                  AOP(right)->aopu.aop_dir,
7790                                  AOP(right)->aopu.aop_dir);
7791                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7792                                  AOP(left)->aopu.aop_dir,
7793                                  AOP(left)->aopu.aop_dir);
7794                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7795                                  AOP(result)->aopu.aop_dir,
7796                                  AOP(result)->aopu.aop_dir);
7797                 }
7798               }
7799             } else {
7800                 // c = bit | val;
7801                 symbol *tlbl = newiTempLabel(NULL);
7802                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7803
7804
7805                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7806                 if( AOP_TYPE(right) == AOP_ACC) {
7807                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7808                   emitSKPNZ;
7809                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7810                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7811                 }
7812
7813
7814
7815                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7816                     pic16_emitcode(";XXX setb","c");
7817                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7818                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7819                 pic16_toBoolean(right);
7820                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7821                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7822                     jmpTrueOrFalse(ifx, tlbl);
7823                     goto release;
7824                 } else {
7825                     CLRC;
7826                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7827                 }
7828             }
7829         }
7830         // bit = c
7831         // val = c
7832         if(size)
7833             pic16_outBitC(result);
7834         // if(bit | ...)
7835         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7836             genIfxJump(ifx, "c");           
7837         goto release ;
7838     }
7839
7840     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7841     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7842     if((AOP_TYPE(right) == AOP_LIT) &&
7843        (AOP_TYPE(result) == AOP_CRY) &&
7844        (AOP_TYPE(left) != AOP_CRY)){
7845         if(lit){
7846           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7847             // result = 1
7848             if(size)
7849                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7850             else 
7851                 continueIfTrue(ifx);
7852             goto release;
7853         } else {
7854           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7855             // lit = 0, result = boolean(left)
7856             if(size)
7857                 pic16_emitcode(";XXX setb","c");
7858             pic16_toBoolean(right);
7859             if(size){
7860                 symbol *tlbl = newiTempLabel(NULL);
7861                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7862                 CLRC;
7863                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7864             } else {
7865                 genIfxJump (ifx,"a");
7866                 goto release;
7867             }
7868         }
7869         pic16_outBitC(result);
7870         goto release ;
7871     }
7872
7873     /* if left is same as result */
7874     if(pic16_sameRegs(AOP(result),AOP(left))){
7875       int know_W = -1;
7876       for(;size--; offset++,lit>>=8) {
7877         if(AOP_TYPE(right) == AOP_LIT){
7878           if((lit & 0xff) == 0)
7879             /*  or'ing with 0 has no effect */
7880             continue;
7881           else {
7882             int p = pic16_my_powof2(lit & 0xff);
7883             if(p>=0) {
7884               /* only one bit is set in the literal, so use a bsf instruction */
7885               pic16_emitpcode(POC_BSF,
7886                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7887             } else {
7888               if(know_W != (lit & 0xff))
7889                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7890               know_W = lit & 0xff;
7891               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7892             }
7893                     
7894           }
7895         } else {
7896           if (AOP_TYPE(left) == AOP_ACC) {
7897             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7898             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7899           } else {                  
7900             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7901             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7902
7903             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7904             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7905
7906           }
7907         }
7908       }
7909     } else {
7910         // left & result in different registers
7911         if(AOP_TYPE(result) == AOP_CRY){
7912             // result = bit
7913             // if(size), result in bit
7914             // if(!size && ifx), conditional oper: if(left | right)
7915             symbol *tlbl = newiTempLabel(NULL);
7916             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7917             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7918
7919
7920             if(size)
7921                 pic16_emitcode(";XXX setb","c");
7922             while(sizer--){
7923                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7924                 pic16_emitcode(";XXX orl","a,%s",
7925                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7926                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7927                 offset++;
7928             }
7929             if(size){
7930                 CLRC;
7931                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7932                 pic16_outBitC(result);
7933             } else if(ifx)
7934                 jmpTrueOrFalse(ifx, tlbl);
7935         } else for(;(size--);offset++){
7936           // normal case
7937           // result = left & right
7938           if(AOP_TYPE(right) == AOP_LIT){
7939             int t = (lit >> (offset*8)) & 0x0FFL;
7940             switch(t) { 
7941             case 0x00:
7942               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7943               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7944
7945               pic16_emitcode("movf","%s,w",
7946                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7947               pic16_emitcode("movwf","%s",
7948                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7949               break;
7950             default:
7951               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7952               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7953               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7954
7955               pic16_emitcode("movlw","0x%x",t);
7956               pic16_emitcode("iorwf","%s,w",
7957                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7958               pic16_emitcode("movwf","%s",
7959                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7960               
7961             }
7962             continue;
7963           }
7964
7965           // faster than result <- left, anl result,right
7966           // and better if result is SFR
7967           if (AOP_TYPE(left) == AOP_ACC) {
7968             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7969             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7970           } else {
7971             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7972             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7973
7974             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7975             pic16_emitcode("iorwf","%s,w",
7976                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7977           }
7978           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7979           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7980         }
7981     }
7982
7983 release :
7984     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7985     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7986     pic16_freeAsmop(result,NULL,ic,TRUE);     
7987 }
7988
7989 /*-----------------------------------------------------------------*/
7990 /* genXor - code for xclusive or                                   */
7991 /*-----------------------------------------------------------------*/
7992 static void genXor (iCode *ic, iCode *ifx)
7993 {
7994   operand *left, *right, *result;
7995   int size, offset=0;
7996   unsigned long lit = 0L;
7997
7998   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7999
8000   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8001   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8002   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8003
8004   /* if left is a literal & right is not ||
8005      if left needs acc & right does not */
8006   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8007       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8008     operand *tmp = right ;
8009     right = left;
8010     left = tmp;
8011   }
8012
8013   /* if result = right then exchange them */
8014   if(pic16_sameRegs(AOP(result),AOP(right))){
8015     operand *tmp = right ;
8016     right = left;
8017     left = tmp;
8018   }
8019
8020   /* if right is bit then exchange them */
8021   if (AOP_TYPE(right) == AOP_CRY &&
8022       AOP_TYPE(left) != AOP_CRY){
8023     operand *tmp = right ;
8024     right = left;
8025     left = tmp;
8026   }
8027   if(AOP_TYPE(right) == AOP_LIT)
8028     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8029
8030   size = AOP_SIZE(result);
8031
8032   // if(bit ^ yy)
8033   // xx = bit ^ yy;
8034   if (AOP_TYPE(left) == AOP_CRY){
8035     if(AOP_TYPE(right) == AOP_LIT){
8036       // c = bit & literal;
8037       if(lit>>1){
8038         // lit>>1  != 0 => result = 1
8039         if(AOP_TYPE(result) == AOP_CRY){
8040           if(size)
8041             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8042             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8043           else if(ifx)
8044             continueIfTrue(ifx);
8045           goto release;
8046         }
8047         pic16_emitcode("setb","c");
8048       } else{
8049         // lit == (0 or 1)
8050         if(lit == 0){
8051           // lit == 0, result = left
8052           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8053             goto release;
8054           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8055         } else{
8056           // lit == 1, result = not(left)
8057           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8058             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8059             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8060             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8061             goto release;
8062           } else {
8063             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8064             pic16_emitcode("cpl","c");
8065           }
8066         }
8067       }
8068
8069     } else {
8070       // right != literal
8071       symbol *tlbl = newiTempLabel(NULL);
8072       if (AOP_TYPE(right) == AOP_CRY){
8073         // c = bit ^ bit;
8074         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8075       }
8076       else{
8077         int sizer = AOP_SIZE(right);
8078         // c = bit ^ val
8079         // if val>>1 != 0, result = 1
8080         pic16_emitcode("setb","c");
8081         while(sizer){
8082           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8083           if(sizer == 1)
8084             // test the msb of the lsb
8085             pic16_emitcode("anl","a,#0xfe");
8086           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8087           sizer--;
8088         }
8089         // val = (0,1)
8090         pic16_emitcode("rrc","a");
8091       }
8092       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8093       pic16_emitcode("cpl","c");
8094       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8095     }
8096     // bit = c
8097     // val = c
8098     if(size)
8099       pic16_outBitC(result);
8100     // if(bit | ...)
8101     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8102       genIfxJump(ifx, "c");           
8103     goto release ;
8104   }
8105
8106   if(pic16_sameRegs(AOP(result),AOP(left))){
8107     /* if left is same as result */
8108     for(;size--; offset++) {
8109       if(AOP_TYPE(right) == AOP_LIT){
8110         int t  = (lit >> (offset*8)) & 0x0FFL;
8111         if(t == 0x00L)
8112           continue;
8113         else
8114           if (IS_AOP_PREG(left)) {
8115             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8116             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8117             pic16_aopPut(AOP(result),"a",offset);
8118           } else {
8119             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8120             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8121             pic16_emitcode("xrl","%s,%s",
8122                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8123                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8124           }
8125       } else {
8126         if (AOP_TYPE(left) == AOP_ACC)
8127           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8128         else {
8129           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8130           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8131 /*
8132           if (IS_AOP_PREG(left)) {
8133             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8134             pic16_aopPut(AOP(result),"a",offset);
8135           } else
8136             pic16_emitcode("xrl","%s,a",
8137                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8138 */
8139         }
8140       }
8141     }
8142   } else {
8143     // left & result in different registers
8144     if(AOP_TYPE(result) == AOP_CRY){
8145       // result = bit
8146       // if(size), result in bit
8147       // if(!size && ifx), conditional oper: if(left ^ right)
8148       symbol *tlbl = newiTempLabel(NULL);
8149       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8150       if(size)
8151         pic16_emitcode("setb","c");
8152       while(sizer--){
8153         if((AOP_TYPE(right) == AOP_LIT) &&
8154            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8155           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8156         } else {
8157           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8158           pic16_emitcode("xrl","a,%s",
8159                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8160         }
8161         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8162         offset++;
8163       }
8164       if(size){
8165         CLRC;
8166         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8167         pic16_outBitC(result);
8168       } else if(ifx)
8169         jmpTrueOrFalse(ifx, tlbl);
8170     } else for(;(size--);offset++){
8171       // normal case
8172       // result = left & right
8173       if(AOP_TYPE(right) == AOP_LIT){
8174         int t = (lit >> (offset*8)) & 0x0FFL;
8175         switch(t) { 
8176         case 0x00:
8177           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8178           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8179           pic16_emitcode("movf","%s,w",
8180                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8181           pic16_emitcode("movwf","%s",
8182                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8183           break;
8184         case 0xff:
8185           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8186           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8187           pic16_emitcode("comf","%s,w",
8188                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8189           pic16_emitcode("movwf","%s",
8190                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8191           break;
8192         default:
8193           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8194           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8195           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8196           pic16_emitcode("movlw","0x%x",t);
8197           pic16_emitcode("xorwf","%s,w",
8198                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8199           pic16_emitcode("movwf","%s",
8200                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8201
8202         }
8203         continue;
8204       }
8205
8206       // faster than result <- left, anl result,right
8207       // and better if result is SFR
8208       if (AOP_TYPE(left) == AOP_ACC) {
8209         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8210         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8211       } else {
8212         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8213         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8214         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8215         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8216       }
8217       if ( AOP_TYPE(result) != AOP_ACC){
8218         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8219         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8220       }
8221     }
8222   }
8223
8224   release :
8225     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8226   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8227   pic16_freeAsmop(result,NULL,ic,TRUE);     
8228 }
8229
8230 /*-----------------------------------------------------------------*/
8231 /* genInline - write the inline code out                           */
8232 /*-----------------------------------------------------------------*/
8233 static void genInline (iCode *ic)
8234 {
8235   char *buffer, *bp, *bp1;
8236     
8237         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8238
8239         _G.inLine += (!options.asmpeep);
8240
8241         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8242         strcpy(buffer,IC_INLINE(ic));
8243         
8244         while((bp1=strstr(bp, "\\n"))) {
8245           *bp1++ = '\n';
8246           *bp1++ = ' ';
8247           bp = bp1;
8248         }
8249         bp = bp1 = buffer;
8250
8251 #if 0
8252   /* This is an experimental code for #pragma inline
8253      and is temporarily disabled for 2.5.0 release */
8254         if(asmInlineMap)
8255         {
8256           symbol *sym;
8257           char *s;
8258           char *cbuf;
8259           int cblen;
8260
8261             cbuf = Safe_strdup(buffer);
8262             cblen = strlen(buffer)+1;
8263             memset(cbuf, 0, cblen);
8264
8265             bp = buffer;
8266             bp1 = cbuf;
8267             while(*bp) {
8268               if(*bp != '%')*bp1++ = *bp++;
8269               else {
8270                 int i;
8271
8272                   bp++;
8273                   i = *bp - '0';
8274                   if(i>elementsInSet(asmInlineMap))break;
8275                   
8276                   bp++;
8277                   s = indexSet(asmInlineMap, i);
8278                   DEBUGpc("searching symbol s = `%s'", s);
8279                   sym = findSym(SymbolTab, NULL, s);
8280
8281                   if(sym->reqv) {
8282                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8283                   } else {
8284                     strcat(bp1, sym->rname);
8285                   }
8286                   
8287                   while(*bp1)bp1++;
8288               }
8289               
8290               if(strlen(bp1) > cblen - 16) {
8291                 int i = strlen(cbuf);
8292                 cblen += 50;
8293                 cbuf = realloc(cbuf, cblen);
8294                 memset(cbuf+i, 0, 50);
8295                 bp1 = cbuf + i;
8296               }
8297             }
8298             
8299             free(buffer);
8300             buffer = Safe_strdup( cbuf );
8301             free(cbuf);
8302             
8303             bp = bp1 = buffer;
8304         }
8305 #endif  /* 0 */
8306
8307         /* emit each line as a code */
8308         while (*bp) {
8309                 if (*bp == '\n') {
8310                         *bp++ = '\0';
8311
8312                         if(*bp1)
8313                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8314                         bp1 = bp;
8315                 } else {
8316                         if (*bp == ':') {
8317                                 bp++;
8318                                 *bp = '\0';
8319                                 bp++;
8320
8321                                 /* print label, use this special format with NULL directive
8322                                  * to denote that the argument should not be indented with tab */
8323                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8324                                 bp1 = bp;
8325                         } else
8326                                 bp++;
8327                 }
8328         }
8329
8330         if ((bp1 != bp) && *bp1)
8331                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8332
8333
8334     Safe_free(buffer);
8335
8336     _G.inLine -= (!options.asmpeep);
8337 }
8338
8339 /*-----------------------------------------------------------------*/
8340 /* genRRC - rotate right with carry                                */
8341 /*-----------------------------------------------------------------*/
8342 static void genRRC (iCode *ic)
8343 {
8344   operand *left , *result ;
8345   int size, offset = 0, same;
8346
8347   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8348
8349   /* rotate right with carry */
8350   left = IC_LEFT(ic);
8351   result=IC_RESULT(ic);
8352   pic16_aopOp (left,ic,FALSE);
8353   pic16_aopOp (result,ic,TRUE);
8354
8355   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8356
8357   same = pic16_sameRegs(AOP(result),AOP(left));
8358
8359   size = AOP_SIZE(result);    
8360
8361   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8362
8363   /* get the lsb and put it into the carry */
8364   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8365
8366   offset = 0 ;
8367
8368   while(size--) {
8369
8370     if(same) {
8371       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8372     } else {
8373       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8374       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8375     }
8376
8377     offset++;
8378   }
8379
8380   pic16_freeAsmop(left,NULL,ic,TRUE);
8381   pic16_freeAsmop(result,NULL,ic,TRUE);
8382 }
8383
8384 /*-----------------------------------------------------------------*/
8385 /* genRLC - generate code for rotate left with carry               */
8386 /*-----------------------------------------------------------------*/
8387 static void genRLC (iCode *ic)
8388 {    
8389   operand *left , *result ;
8390   int size, offset = 0;
8391   int same;
8392
8393   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8394   /* rotate right with carry */
8395   left = IC_LEFT(ic);
8396   result=IC_RESULT(ic);
8397   pic16_aopOp (left,ic,FALSE);
8398   pic16_aopOp (result,ic,TRUE);
8399
8400   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8401
8402   same = pic16_sameRegs(AOP(result),AOP(left));
8403
8404   /* move it to the result */
8405   size = AOP_SIZE(result);    
8406
8407   /* get the msb and put it into the carry */
8408   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8409
8410   offset = 0 ;
8411
8412   while(size--) {
8413
8414     if(same) {
8415       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8416     } else {
8417       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8418       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8419     }
8420
8421     offset++;
8422   }
8423
8424
8425   pic16_freeAsmop(left,NULL,ic,TRUE);
8426   pic16_freeAsmop(result,NULL,ic,TRUE);
8427 }
8428
8429
8430 /* gpasm can get the highest order bit with HIGH/UPPER
8431  * so the following probably is not needed -- VR */
8432  
8433 /*-----------------------------------------------------------------*/
8434 /* genGetHbit - generates code get highest order bit               */
8435 /*-----------------------------------------------------------------*/
8436 static void genGetHbit (iCode *ic)
8437 {
8438     operand *left, *result;
8439     left = IC_LEFT(ic);
8440     result=IC_RESULT(ic);
8441     pic16_aopOp (left,ic,FALSE);
8442     pic16_aopOp (result,ic,FALSE);
8443
8444     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8445     /* get the highest order byte into a */
8446     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8447     if(AOP_TYPE(result) == AOP_CRY){
8448         pic16_emitcode("rlc","a");
8449         pic16_outBitC(result);
8450     }
8451     else{
8452         pic16_emitcode("rl","a");
8453         pic16_emitcode("anl","a,#0x01");
8454         pic16_outAcc(result);
8455     }
8456
8457
8458     pic16_freeAsmop(left,NULL,ic,TRUE);
8459     pic16_freeAsmop(result,NULL,ic,TRUE);
8460 }
8461
8462 #if 0
8463 /*-----------------------------------------------------------------*/
8464 /* AccRol - rotate left accumulator by known count                 */
8465 /*-----------------------------------------------------------------*/
8466 static void AccRol (int shCount)
8467 {
8468     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8469     shCount &= 0x0007;              // shCount : 0..7
8470     switch(shCount){
8471         case 0 :
8472             break;
8473         case 1 :
8474             pic16_emitcode("rl","a");
8475             break;
8476         case 2 :
8477             pic16_emitcode("rl","a");
8478             pic16_emitcode("rl","a");
8479             break;
8480         case 3 :
8481             pic16_emitcode("swap","a");
8482             pic16_emitcode("rr","a");
8483             break;
8484         case 4 :
8485             pic16_emitcode("swap","a");
8486             break;
8487         case 5 :
8488             pic16_emitcode("swap","a");
8489             pic16_emitcode("rl","a");
8490             break;
8491         case 6 :
8492             pic16_emitcode("rr","a");
8493             pic16_emitcode("rr","a");
8494             break;
8495         case 7 :
8496             pic16_emitcode("rr","a");
8497             break;
8498     }
8499 }
8500 #endif
8501
8502 /*-----------------------------------------------------------------*/
8503 /* AccLsh - left shift accumulator by known count                  */
8504 /*-----------------------------------------------------------------*/
8505 static void AccLsh (int shCount)
8506 {
8507         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8508         switch(shCount){
8509                 case 0 :
8510                         return;
8511                         break;
8512                 case 1 :
8513                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8514                         break;
8515                 case 2 :
8516                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8517                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8518                         break;
8519                 case 3 :
8520                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8521                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8522                         break;
8523                 case 4 :
8524                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8525                         break;
8526                 case 5 :
8527                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8528                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8529                         break;
8530                 case 6 :
8531                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8532                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8533                         break;
8534                 case 7 :
8535                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8536                         break;
8537         }
8538
8539         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8540 }
8541
8542 /*-----------------------------------------------------------------*/
8543 /* AccRsh - right shift accumulator by known count                 */
8544 /*-----------------------------------------------------------------*/
8545 static void AccRsh (int shCount, int andmask)
8546 {
8547         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8548         switch(shCount){
8549                 case 0 :
8550                         return; break;
8551                 case 1 :
8552                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8553                         break;
8554                 case 2 :
8555                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8556                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8557                         break;
8558                 case 3 :
8559                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8560                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8561                         break;
8562                 case 4 :
8563                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8564                         break;
8565                 case 5 :
8566                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8567                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8568                         break;
8569                 case 6 :
8570                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8571                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8572                         break;
8573                 case 7 :
8574                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8575                         break;
8576         }
8577         
8578         if(andmask)
8579                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8580         else
8581                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8582 }
8583
8584 #if 0
8585 /*-----------------------------------------------------------------*/
8586 /* AccSRsh - signed right shift accumulator by known count                 */
8587 /*-----------------------------------------------------------------*/
8588 static void AccSRsh (int shCount)
8589 {
8590     symbol *tlbl ;
8591     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8592     if(shCount != 0){
8593         if(shCount == 1){
8594             pic16_emitcode("mov","c,acc.7");
8595             pic16_emitcode("rrc","a");
8596         } else if(shCount == 2){
8597             pic16_emitcode("mov","c,acc.7");
8598             pic16_emitcode("rrc","a");
8599             pic16_emitcode("mov","c,acc.7");
8600             pic16_emitcode("rrc","a");
8601         } else {
8602             tlbl = newiTempLabel(NULL);
8603             /* rotate right accumulator */
8604             AccRol(8 - shCount);
8605             /* and kill the higher order bits */
8606             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8607             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8608             pic16_emitcode("orl","a,#0x%02x",
8609                      (unsigned char)~SRMask[shCount]);
8610             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8611         }
8612     }
8613 }
8614 #endif
8615
8616 /*-----------------------------------------------------------------*/
8617 /* shiftR1Left2Result - shift right one byte from left to result   */
8618 /*-----------------------------------------------------------------*/
8619 static void shiftR1Left2ResultSigned (operand *left, int offl,
8620                                 operand *result, int offr,
8621                                 int shCount)
8622 {
8623   int same;
8624
8625   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8626
8627   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8628
8629   switch(shCount) {
8630   case 1:
8631     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8632     if(same) 
8633       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8634     else {
8635       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8636       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8637     }
8638
8639     break;
8640   case 2:
8641
8642     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8643     if(same) 
8644       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8645     else {
8646       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8647       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8648     }
8649     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8650     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8651
8652     break;
8653
8654   case 3:
8655     if(same)
8656       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8657     else {
8658       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8659       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8660     }
8661
8662     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8663     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8664     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8665
8666     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8667     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8668
8669     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8670     break;
8671
8672   case 4:
8673     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8674     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8675     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8676     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8677     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8678     break;
8679   case 5:
8680     if(same) {
8681       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8682     } else {
8683       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8684       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8685     }
8686     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8687     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8688     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8689     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8690     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8691     break;
8692
8693   case 6:
8694     if(same) {
8695       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8696       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8697       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8698       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8699       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8700       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8701     } else {
8702       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8703       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8704       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8705       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8706       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8707     }
8708     break;
8709
8710   case 7:
8711     if(same) {
8712       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8713       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8714       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8715       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8716     } else {
8717       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8718       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8719       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8720     }
8721
8722   default:
8723     break;
8724   }
8725 }
8726
8727 /*-----------------------------------------------------------------*/
8728 /* shiftR1Left2Result - shift right one byte from left to result   */
8729 /*-----------------------------------------------------------------*/
8730 static void shiftR1Left2Result (operand *left, int offl,
8731                                 operand *result, int offr,
8732                                 int shCount, int sign)
8733 {
8734   int same;
8735
8736   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8737
8738   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8739
8740   /* Copy the msb into the carry if signed. */
8741   if(sign) {
8742     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8743     return;
8744   }
8745
8746
8747
8748   switch(shCount) {
8749   case 1:
8750     emitCLRC;
8751     if(same) 
8752       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8753     else {
8754       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8755       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8756     }
8757     break;
8758   case 2:
8759     emitCLRC;
8760     if(same) {
8761       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8762     } else {
8763       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8764       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8765     }
8766     emitCLRC;
8767     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8768
8769     break;
8770   case 3:
8771     if(same)
8772       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8773     else {
8774       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8775       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8776     }
8777
8778     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8779     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8780     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8781     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8782     break;
8783       
8784   case 4:
8785     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8786     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8787     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8788     break;
8789
8790   case 5:
8791     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8792     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8793     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8794     //emitCLRC;
8795     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8796
8797     break;
8798   case 6:
8799
8800     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8801     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8802     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8803     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8804     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8805     break;
8806
8807   case 7:
8808
8809     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8810     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8811     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8812
8813     break;
8814
8815   default:
8816     break;
8817   }
8818 }
8819
8820 /*-----------------------------------------------------------------*/
8821 /* shiftL1Left2Result - shift left one byte from left to result    */
8822 /*-----------------------------------------------------------------*/
8823 static void shiftL1Left2Result (operand *left, int offl,
8824                                 operand *result, int offr, int shCount)
8825 {
8826   int same;
8827
8828   //    char *l;
8829   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8830
8831   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8832   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8833     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8834     //    MOVA(l);
8835     /* shift left accumulator */
8836     //AccLsh(shCount); // don't comment out just yet...
8837   //    pic16_aopPut(AOP(result),"a",offr);
8838
8839   switch(shCount) {
8840   case 1:
8841     /* Shift left 1 bit position */
8842     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8843     if(same) {
8844       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8845     } else {
8846       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8847       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8848     }
8849     break;
8850   case 2:
8851     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8852     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8853     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8854     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8855     break;
8856   case 3:
8857     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8858     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8859     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8860     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8861     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8862     break;
8863   case 4:
8864     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8865     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8866     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8867     break;
8868   case 5:
8869     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8870     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8871     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8872     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8873     break;
8874   case 6:
8875     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8876     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8877     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8878     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8879     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8880     break;
8881   case 7:
8882     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8883     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8884     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8885     break;
8886
8887   default:
8888     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8889   }
8890
8891 }
8892
8893 /*-----------------------------------------------------------------*/
8894 /* movLeft2Result - move byte from left to result                  */
8895 /*-----------------------------------------------------------------*/
8896 static void movLeft2Result (operand *left, int offl,
8897                             operand *result, int offr)
8898 {
8899   char *l;
8900   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8901   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8902     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8903
8904     if (*l == '@' && (IS_AOP_PREG(result))) {
8905       pic16_emitcode("mov","a,%s",l);
8906       pic16_aopPut(AOP(result),"a",offr);
8907     } else {
8908       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8909       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8910     }
8911   }
8912 }
8913
8914 /*-----------------------------------------------------------------*/
8915 /* shiftL2Left2Result - shift left two bytes from left to result   */
8916 /*-----------------------------------------------------------------*/
8917 static void shiftL2Left2Result (operand *left, int offl,
8918                                 operand *result, int offr, int shCount)
8919 {
8920   int same = pic16_sameRegs(AOP(result), AOP(left));
8921   int i;
8922
8923   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8924
8925   if (same && (offl != offr)) { // shift bytes
8926     if (offr > offl) {
8927        for(i=1;i>-1;i--) {
8928          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8929          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8930        }
8931     } else { // just treat as different later on
8932                 same = 0;
8933     }
8934   }
8935
8936   if(same) {
8937     switch(shCount) {
8938     case 0:
8939       break;
8940     case 1:
8941     case 2:
8942     case 3:
8943
8944       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8945       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8946       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8947
8948       while(--shCount) {
8949                 emitCLRC;
8950                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8951                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8952       }
8953
8954       break;
8955     case 4:
8956     case 5:
8957       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8958       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8959       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8960       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8961       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8962       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8963       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8964       if(shCount >=5) {
8965                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8966                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8967       }
8968       break;
8969     case 6:
8970       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8971       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8972       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8973       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8974       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8975       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8976       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8977       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8978       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8979       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8980       break;
8981     case 7:
8982       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8983       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8984       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8985       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8986       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8987     }
8988
8989   } else {
8990     switch(shCount) {
8991     case 0:
8992       break;
8993     case 1:
8994     case 2:
8995     case 3:
8996       /* note, use a mov/add for the shift since the mov has a
8997          chance of getting optimized out */
8998       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8999       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9000       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9001       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9002       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9003
9004       while(--shCount) {
9005                 emitCLRC;
9006                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9007                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9008       }
9009       break;
9010
9011     case 4:
9012     case 5:
9013       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9014       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9015       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9016       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9017       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9018       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9019       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9020       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9021
9022
9023       if(shCount == 5) {
9024                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9025                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9026       }
9027       break;
9028     case 6:
9029       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9030       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9031       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9032       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9033
9034       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9035       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9036       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9037       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9038       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9039       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9040       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9041       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9042       break;
9043     case 7:
9044       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9045       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9046       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9047       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9048       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9049     }
9050   }
9051
9052 }
9053 /*-----------------------------------------------------------------*/
9054 /* shiftR2Left2Result - shift right two bytes from left to result  */
9055 /*-----------------------------------------------------------------*/
9056 static void shiftR2Left2Result (operand *left, int offl,
9057                                 operand *result, int offr,
9058                                 int shCount, int sign)
9059 {
9060   int same = pic16_sameRegs(AOP(result), AOP(left));
9061   int i;
9062   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9063
9064   if (same && (offl != offr)) { // shift right bytes
9065     if (offr < offl) {
9066        for(i=0;i<2;i++) {
9067          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9068          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9069        }
9070     } else { // just treat as different later on
9071                 same = 0;
9072     }
9073   }
9074
9075   switch(shCount) {
9076   case 0:
9077     break;
9078   case 1:
9079   case 2:
9080   case 3:
9081     if(sign)
9082       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9083     else
9084       emitCLRC;
9085
9086     if(same) {
9087       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9088       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9089     } else {
9090       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9091       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9092       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9093       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9094     }
9095
9096     while(--shCount) {
9097       if(sign)
9098                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9099       else
9100                 emitCLRC;
9101       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9102       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9103     }
9104     break;
9105   case 4:
9106   case 5:
9107     if(same) {
9108
9109       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9110       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9111       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9112
9113       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9114       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9115       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9116       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9117     } else {
9118       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9119       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9120       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9121
9122       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9123       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9124       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9125       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9126       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9127     }
9128
9129     if(shCount >=5) {
9130       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9131       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9132     }
9133
9134     if(sign) {
9135       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9136       pic16_emitpcode(POC_BTFSC, 
9137                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9138       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9139     }
9140
9141     break;
9142
9143   case 6:
9144     if(same) {
9145
9146       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9147       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9148
9149       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9150       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9151       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9152       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9153       if(sign) {
9154         pic16_emitpcode(POC_BTFSC, 
9155                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9156         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9157       }
9158       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9159       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9160       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9161       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9162     } else {
9163       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9164       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9165       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9166       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9167       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9168       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9169       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9170       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9171       if(sign) {
9172         pic16_emitpcode(POC_BTFSC, 
9173                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9174         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9175       }
9176       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9177       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9178
9179         
9180     }
9181
9182     break;
9183   case 7:
9184     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9185     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9186     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9187     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9188     if(sign) {
9189       emitSKPNC;
9190       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9191     } else 
9192       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9193   }
9194 }
9195
9196
9197 /*-----------------------------------------------------------------*/
9198 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9199 /*-----------------------------------------------------------------*/
9200 static void shiftLLeftOrResult (operand *left, int offl,
9201                                 operand *result, int offr, int shCount)
9202 {
9203     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9204
9205     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9206     /* shift left accumulator */
9207     AccLsh(shCount);
9208     /* or with result */
9209     /* back to result */
9210     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9211 }
9212
9213 /*-----------------------------------------------------------------*/
9214 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9215 /*-----------------------------------------------------------------*/
9216 static void shiftRLeftOrResult (operand *left, int offl,
9217                                 operand *result, int offr, int shCount)
9218 {
9219     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9220     
9221     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9222     /* shift right accumulator */
9223     AccRsh(shCount, 1);
9224     /* or with result */
9225     /* back to result */
9226     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9227 }
9228
9229 /*-----------------------------------------------------------------*/
9230 /* genlshOne - left shift a one byte quantity by known count       */
9231 /*-----------------------------------------------------------------*/
9232 static void genlshOne (operand *result, operand *left, int shCount)
9233 {       
9234     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9235     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9236 }
9237
9238 /*-----------------------------------------------------------------*/
9239 /* genlshTwo - left shift two bytes by known amount != 0           */
9240 /*-----------------------------------------------------------------*/
9241 static void genlshTwo (operand *result,operand *left, int shCount)
9242 {
9243     int size;
9244     
9245     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9246     size = pic16_getDataSize(result);
9247
9248     /* if shCount >= 8 */
9249     if (shCount >= 8) {
9250         shCount -= 8 ;
9251
9252         if (size > 1){
9253             if (shCount)
9254                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9255             else 
9256                 movLeft2Result(left, LSB, result, MSB16);
9257         }
9258         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9259     }
9260
9261     /*  1 <= shCount <= 7 */
9262     else {  
9263         if(size == 1)
9264             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9265         else 
9266             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9267     }
9268 }
9269
9270 /*-----------------------------------------------------------------*/
9271 /* shiftLLong - shift left one long from left to result            */
9272 /* offr = LSB or MSB16                                             */
9273 /*-----------------------------------------------------------------*/
9274 static void shiftLLong (operand *left, operand *result, int offr )
9275 {
9276     int size = AOP_SIZE(result);
9277     int same = pic16_sameRegs(AOP(left),AOP(result));
9278         int i;
9279
9280     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9281
9282         if (same && (offr == MSB16)) { //shift one byte
9283                 for(i=size-1;i>=MSB16;i--) {
9284                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9285                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9286                 }
9287         } else {
9288                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9289         }
9290         
9291     if (size > LSB+offr ){
9292                 if (same) {
9293                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9294                 } else {
9295                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9296                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9297                 }
9298          }
9299
9300     if(size > MSB16+offr){
9301                 if (same) {
9302                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9303                 } else {
9304                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9305                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9306                 }
9307     }
9308
9309     if(size > MSB24+offr){
9310                 if (same) {
9311                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9312                 } else {
9313                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9314                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9315                 }
9316     }
9317
9318     if(size > MSB32+offr){
9319                 if (same) {
9320                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9321                 } else {
9322                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9323                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9324                 }
9325     }
9326     if(offr != LSB)
9327                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9328
9329 }
9330
9331 /*-----------------------------------------------------------------*/
9332 /* genlshFour - shift four byte by a known amount != 0             */
9333 /*-----------------------------------------------------------------*/
9334 static void genlshFour (operand *result, operand *left, int shCount)
9335 {
9336     int size;
9337
9338     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9339     size = AOP_SIZE(result);
9340
9341     /* if shifting more that 3 bytes */
9342     if (shCount >= 24 ) {
9343         shCount -= 24;
9344         if (shCount)
9345             /* lowest order of left goes to the highest
9346             order of the destination */
9347             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9348         else
9349             movLeft2Result(left, LSB, result, MSB32);
9350
9351                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9352                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9353                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9354
9355         return;
9356     }
9357
9358     /* more than two bytes */
9359     else if ( shCount >= 16 ) {
9360         /* lower order two bytes goes to higher order two bytes */
9361         shCount -= 16;
9362         /* if some more remaining */
9363         if (shCount)
9364             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9365         else {
9366             movLeft2Result(left, MSB16, result, MSB32);
9367             movLeft2Result(left, LSB, result, MSB24);
9368         }
9369                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9370                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9371         return;
9372     }    
9373
9374     /* if more than 1 byte */
9375     else if ( shCount >= 8 ) {
9376         /* lower order three bytes goes to higher order  three bytes */
9377         shCount -= 8;
9378         if(size == 2){
9379             if(shCount)
9380                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9381             else
9382                 movLeft2Result(left, LSB, result, MSB16);
9383         }
9384         else{   /* size = 4 */
9385             if(shCount == 0){
9386                 movLeft2Result(left, MSB24, result, MSB32);
9387                 movLeft2Result(left, MSB16, result, MSB24);
9388                 movLeft2Result(left, LSB, result, MSB16);
9389                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9390             }
9391             else if(shCount == 1)
9392                 shiftLLong(left, result, MSB16);
9393             else{
9394                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9395                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9396                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9397                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9398             }
9399         }
9400     }
9401
9402     /* 1 <= shCount <= 7 */
9403     else if(shCount <= 3)
9404     { 
9405         shiftLLong(left, result, LSB);
9406         while(--shCount >= 1)
9407             shiftLLong(result, result, LSB);
9408     }
9409     /* 3 <= shCount <= 7, optimize */
9410     else{
9411         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9412         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9413         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9414     }
9415 }
9416
9417 /*-----------------------------------------------------------------*/
9418 /* genLeftShiftLiteral - left shifting by known count              */
9419 /*-----------------------------------------------------------------*/
9420 void pic16_genLeftShiftLiteral (operand *left,
9421                                  operand *right,
9422                                  operand *result,
9423                                  iCode *ic)
9424 {    
9425     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9426     int size;
9427
9428     FENTRY;
9429     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9430     pic16_freeAsmop(right,NULL,ic,TRUE);
9431
9432     pic16_aopOp(left,ic,FALSE);
9433     pic16_aopOp(result,ic,TRUE);
9434
9435     size = getSize(operandType(result));
9436
9437 #if VIEW_SIZE
9438     pic16_emitcode("; shift left ","result %d, left %d",size,
9439              AOP_SIZE(left));
9440 #endif
9441
9442     /* I suppose that the left size >= result size */
9443     if(shCount == 0){
9444         while(size--){
9445             movLeft2Result(left, size, result, size);
9446         }
9447     }
9448
9449     else if(shCount >= (size * 8))
9450         while(size--)
9451             pic16_aopPut(AOP(result),zero,size);
9452     else{
9453         switch (size) {
9454             case 1:
9455                 genlshOne (result,left,shCount);
9456                 break;
9457
9458             case 2:
9459             case 3:
9460                 genlshTwo (result,left,shCount);
9461                 break;
9462
9463             case 4:
9464                 genlshFour (result,left,shCount);
9465                 break;
9466         }
9467     }
9468     pic16_freeAsmop(left,NULL,ic,TRUE);
9469     pic16_freeAsmop(result,NULL,ic,TRUE);
9470 }
9471
9472 /*-----------------------------------------------------------------*
9473  * genMultiAsm - repeat assembly instruction for size of register.
9474  * if endian == 1, then the high byte (i.e base address + size of 
9475  * register) is used first else the low byte is used first;
9476  *-----------------------------------------------------------------*/
9477 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9478 {
9479
9480   int offset = 0;
9481
9482   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9483
9484   if(!reg)
9485     return;
9486
9487   if(!endian) {
9488     endian = 1;
9489   } else {
9490     endian = -1;
9491     offset = size-1;
9492   }
9493
9494   while(size--) {
9495     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9496     offset += endian;
9497   }
9498
9499 }
9500
9501 #if !(USE_GENERIC_SIGNED_SHIFT)
9502 /*-----------------------------------------------------------------*/
9503 /* genLeftShift - generates code for left shifting                 */
9504 /*-----------------------------------------------------------------*/
9505 static void genLeftShift (iCode *ic)
9506 {
9507   operand *left,*right, *result;
9508   int size, offset;
9509 //  char *l;
9510   symbol *tlbl , *tlbl1;
9511   pCodeOp *pctemp;
9512
9513   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9514
9515   right = IC_RIGHT(ic);
9516   left  = IC_LEFT(ic);
9517   result = IC_RESULT(ic);
9518
9519   pic16_aopOp(right,ic,FALSE);
9520
9521   /* if the shift count is known then do it 
9522      as efficiently as possible */
9523   if (AOP_TYPE(right) == AOP_LIT) {
9524     pic16_genLeftShiftLiteral (left,right,result,ic);
9525     return ;
9526   }
9527
9528   /* shift count is unknown then we have to form
9529    * a loop. Get the loop count in WREG : Note: we take
9530    * only the lower order byte since shifting
9531    * more than 32 bits make no sense anyway, ( the
9532    * largest size of an object can be only 32 bits ) */
9533   
9534   pic16_aopOp(left,ic,FALSE);
9535   pic16_aopOp(result,ic,FALSE);
9536
9537   /* now move the left to the result if they are not the
9538    * same, and if size > 1,
9539    * and if right is not same to result (!!!) -- VR */
9540   if (!pic16_sameRegs(AOP(left),AOP(result))
9541       && (AOP_SIZE(result) > 1)) {
9542
9543     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9544
9545     size = AOP_SIZE(result);
9546     offset=0;
9547     while (size--) {
9548
9549 #if 0
9550       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9551       if (*l == '@' && (IS_AOP_PREG(result))) {
9552
9553           pic16_emitcode("mov","a,%s",l);
9554           pic16_aopPut(AOP(result),"a",offset);
9555       } else
9556 #endif
9557       {
9558         /* we don't know if left is a literal or a register, take care -- VR */
9559         pic16_mov2f(AOP(result), AOP(left), offset);
9560       }
9561       offset++;
9562     }
9563   }
9564
9565   size = AOP_SIZE(result);
9566
9567   /* if it is only one byte then */
9568   if (size == 1) {
9569     if(optimized_for_speed) {
9570       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9571       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9572       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9573       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9574       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9575       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9576       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9577       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9578       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9579       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9580       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9581       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9582     } else {
9583
9584       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9585
9586       tlbl = newiTempLabel(NULL);
9587
9588 #if 1
9589       /* this is already done, why change it? */
9590       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9591                 pic16_mov2f(AOP(result), AOP(left), 0);
9592       }
9593 #endif
9594
9595       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9596       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9597       pic16_emitpLabel(tlbl->key);
9598       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9599       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9600       emitSKPC;
9601       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9602     }
9603     goto release ;
9604   }
9605     
9606   if (pic16_sameRegs(AOP(left),AOP(result))) {
9607
9608     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9609     
9610     tlbl = newiTempLabel(NULL);
9611     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9612     genMultiAsm(POC_RRCF, result, size,1);
9613     pic16_emitpLabel(tlbl->key);
9614     genMultiAsm(POC_RLCF, result, size,0);
9615     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9616     emitSKPC;
9617     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9618     goto release;
9619   }
9620
9621   //tlbl = newiTempLabel(NULL);
9622   //offset = 0 ;   
9623   //tlbl1 = newiTempLabel(NULL);
9624
9625   //reAdjustPreg(AOP(result));    
9626     
9627   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9628   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9629   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9630   //MOVA(l);
9631   //pic16_emitcode("add","a,acc");         
9632   //pic16_aopPut(AOP(result),"a",offset++);
9633   //while (--size) {
9634   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9635   //  MOVA(l);
9636   //  pic16_emitcode("rlc","a");         
9637   //  pic16_aopPut(AOP(result),"a",offset++);
9638   //}
9639   //reAdjustPreg(AOP(result));
9640
9641   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9642   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9643
9644
9645   tlbl = newiTempLabel(NULL);
9646   tlbl1= newiTempLabel(NULL);
9647
9648   size = AOP_SIZE(result);
9649   offset = 1;
9650
9651   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9652
9653   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9654
9655   /* offset should be 0, 1 or 3 */
9656   
9657   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9658   emitSKPNZ;
9659   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9660
9661   pic16_emitpcode(POC_MOVWF, pctemp);
9662
9663
9664   pic16_emitpLabel(tlbl->key);
9665
9666   emitCLRC;
9667   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9668   while(--size)
9669     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9670
9671   pic16_emitpcode(POC_DECFSZ,  pctemp);
9672   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9673   pic16_emitpLabel(tlbl1->key);
9674
9675   pic16_popReleaseTempReg(pctemp,1);
9676
9677
9678  release:
9679   pic16_freeAsmop (right,NULL,ic,TRUE);
9680   pic16_freeAsmop(left,NULL,ic,TRUE);
9681   pic16_freeAsmop(result,NULL,ic,TRUE);
9682 }
9683 #endif
9684
9685
9686 #if 0
9687 #error old code (left here for reference)
9688 /*-----------------------------------------------------------------*/
9689 /* genLeftShift - generates code for left shifting                 */
9690 /*-----------------------------------------------------------------*/
9691 static void genLeftShift (iCode *ic)
9692 {
9693   operand *left,*right, *result;
9694   int size, offset;
9695   char *l;
9696   symbol *tlbl , *tlbl1;
9697   pCodeOp *pctemp;
9698
9699   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9700
9701   right = IC_RIGHT(ic);
9702   left  = IC_LEFT(ic);
9703   result = IC_RESULT(ic);
9704
9705   pic16_aopOp(right,ic,FALSE);
9706
9707   /* if the shift count is known then do it 
9708      as efficiently as possible */
9709   if (AOP_TYPE(right) == AOP_LIT) {
9710     pic16_genLeftShiftLiteral (left,right,result,ic);
9711     return ;
9712   }
9713
9714   /* shift count is unknown then we have to form 
9715      a loop get the loop count in B : Note: we take
9716      only the lower order byte since shifting
9717      more that 32 bits make no sense anyway, ( the
9718      largest size of an object can be only 32 bits ) */  
9719
9720     
9721   pic16_aopOp(left,ic,FALSE);
9722   pic16_aopOp(result,ic,FALSE);
9723
9724   /* now move the left to the result if they are not the
9725      same */
9726   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9727       AOP_SIZE(result) > 1) {
9728
9729     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9730
9731     size = AOP_SIZE(result);
9732     offset=0;
9733     while (size--) {
9734       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9735       if (*l == '@' && (IS_AOP_PREG(result))) {
9736
9737         pic16_emitcode("mov","a,%s",l);
9738         pic16_aopPut(AOP(result),"a",offset);
9739       } else {
9740
9741         /* we don't know if left is a literal or a register, take care -- VR */
9742         pic16_mov2f(AOP(result), AOP(left), offset);
9743       }
9744       offset++;
9745     }
9746   }
9747
9748   size = AOP_SIZE(result);
9749
9750   /* if it is only one byte then */
9751   if (size == 1) {
9752     if(optimized_for_speed) {
9753       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9754       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9755       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9756       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9757       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9758       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9759       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9760       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9761       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9762       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9763       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9764       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9765     } else {
9766
9767       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9768
9769       tlbl = newiTempLabel(NULL);
9770       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9771                 pic16_mov2f(AOP(result), AOP(left), 0);
9772                 
9773 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9774 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9775       }
9776
9777       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9778       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9779       pic16_emitpLabel(tlbl->key);
9780       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9781       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9782       emitSKPC;
9783       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9784     }
9785     goto release ;
9786   }
9787     
9788   if (pic16_sameRegs(AOP(left),AOP(result))) {
9789
9790     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9791     
9792     tlbl = newiTempLabel(NULL);
9793     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9794     genMultiAsm(POC_RRCF, result, size,1);
9795     pic16_emitpLabel(tlbl->key);
9796     genMultiAsm(POC_RLCF, result, size,0);
9797     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9798     emitSKPC;
9799     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9800     goto release;
9801   }
9802
9803   //tlbl = newiTempLabel(NULL);
9804   //offset = 0 ;   
9805   //tlbl1 = newiTempLabel(NULL);
9806
9807   //reAdjustPreg(AOP(result));    
9808     
9809   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9810   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9811   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9812   //MOVA(l);
9813   //pic16_emitcode("add","a,acc");         
9814   //pic16_aopPut(AOP(result),"a",offset++);
9815   //while (--size) {
9816   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9817   //  MOVA(l);
9818   //  pic16_emitcode("rlc","a");         
9819   //  pic16_aopPut(AOP(result),"a",offset++);
9820   //}
9821   //reAdjustPreg(AOP(result));
9822
9823   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9824   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9825
9826
9827   tlbl = newiTempLabel(NULL);
9828   tlbl1= newiTempLabel(NULL);
9829
9830   size = AOP_SIZE(result);
9831   offset = 1;
9832
9833   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9834
9835   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9836
9837   /* offset should be 0, 1 or 3 */
9838   
9839   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9840   emitSKPNZ;
9841   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9842
9843   pic16_emitpcode(POC_MOVWF, pctemp);
9844
9845
9846   pic16_emitpLabel(tlbl->key);
9847
9848   emitCLRC;
9849   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9850   while(--size)
9851     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9852
9853   pic16_emitpcode(POC_DECFSZ,  pctemp);
9854   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9855   pic16_emitpLabel(tlbl1->key);
9856
9857   pic16_popReleaseTempReg(pctemp,1);
9858
9859
9860  release:
9861   pic16_freeAsmop (right,NULL,ic,TRUE);
9862   pic16_freeAsmop(left,NULL,ic,TRUE);
9863   pic16_freeAsmop(result,NULL,ic,TRUE);
9864 }
9865 #endif
9866
9867 /*-----------------------------------------------------------------*/
9868 /* genrshOne - right shift a one byte quantity by known count      */
9869 /*-----------------------------------------------------------------*/
9870 static void genrshOne (operand *result, operand *left,
9871                        int shCount, int sign)
9872 {
9873     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9874     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9875 }
9876
9877 /*-----------------------------------------------------------------*/
9878 /* genrshTwo - right shift two bytes by known amount != 0          */
9879 /*-----------------------------------------------------------------*/
9880 static void genrshTwo (operand *result,operand *left,
9881                        int shCount, int sign)
9882 {
9883   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9884   /* if shCount >= 8 */
9885   if (shCount >= 8) {
9886     shCount -= 8 ;
9887     if (shCount)
9888       shiftR1Left2Result(left, MSB16, result, LSB,
9889                          shCount, sign);
9890     else
9891       movLeft2Result(left, MSB16, result, LSB);
9892
9893     pic16_addSign (result, 1, sign);
9894   }
9895
9896   /*  1 <= shCount <= 7 */
9897   else
9898     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9899 }
9900
9901 /*-----------------------------------------------------------------*/
9902 /* shiftRLong - shift right one long from left to result           */
9903 /* offl = LSB or MSB16                                             */
9904 /*-----------------------------------------------------------------*/
9905 static void shiftRLong (operand *left, int offl,
9906                         operand *result, int sign)
9907 {
9908     int size = AOP_SIZE(result);
9909     int same = pic16_sameRegs(AOP(left),AOP(result));
9910     int i;
9911     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9912
9913         if (same && (offl == MSB16)) { //shift one byte right
9914                 for(i=MSB16;i<size;i++) {
9915                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9916                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9917                 }
9918         }
9919
9920     if(sign)
9921                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9922         else
9923                 emitCLRC;
9924
9925         if (same) {
9926                 if (offl == LSB)
9927                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9928         } else {
9929         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9930         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9931         }
9932
9933     if(offl == MSB16) {
9934         /* add sign of "a" */
9935         pic16_addSign(result, MSB32, sign);
9936         }
9937
9938         if (same) {
9939         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9940         } else {
9941         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9942         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9943         }
9944         
9945         if (same) {
9946         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9947         } else {
9948         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9949         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9950         }
9951
9952         if (same) {
9953         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9954         } else {
9955         if(offl == LSB){
9956                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9957                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9958         }
9959         }
9960 }
9961
9962 /*-----------------------------------------------------------------*/
9963 /* genrshFour - shift four byte by a known amount != 0             */
9964 /*-----------------------------------------------------------------*/
9965 static void genrshFour (operand *result, operand *left,
9966                         int shCount, int sign)
9967 {
9968   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9969   /* if shifting more that 3 bytes */
9970   if(shCount >= 24 ) {
9971     shCount -= 24;
9972     if(shCount)
9973       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9974     else
9975       movLeft2Result(left, MSB32, result, LSB);
9976
9977     pic16_addSign(result, MSB16, sign);
9978   }
9979   else if(shCount >= 16){
9980     shCount -= 16;
9981     if(shCount)
9982       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9983     else{
9984       movLeft2Result(left, MSB24, result, LSB);
9985       movLeft2Result(left, MSB32, result, MSB16);
9986     }
9987     pic16_addSign(result, MSB24, sign);
9988   }
9989   else if(shCount >= 8){
9990     shCount -= 8;
9991     if(shCount == 1)
9992       shiftRLong(left, MSB16, result, sign);
9993     else if(shCount == 0){
9994       movLeft2Result(left, MSB16, result, LSB);
9995       movLeft2Result(left, MSB24, result, MSB16);
9996       movLeft2Result(left, MSB32, result, MSB24);
9997       pic16_addSign(result, MSB32, sign);
9998     }
9999     else{ //shcount >= 2
10000       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10001       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10002       /* the last shift is signed */
10003       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10004       pic16_addSign(result, MSB32, sign);
10005     }
10006   }
10007   else{   /* 1 <= shCount <= 7 */
10008     if(shCount <= 2){
10009       shiftRLong(left, LSB, result, sign);
10010       if(shCount == 2)
10011         shiftRLong(result, LSB, result, sign);
10012     }
10013     else{
10014       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10015       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10016       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10017     }
10018   }
10019 }
10020
10021 /*-----------------------------------------------------------------*/
10022 /* genRightShiftLiteral - right shifting by known count            */
10023 /*-----------------------------------------------------------------*/
10024 static void genRightShiftLiteral (operand *left,
10025                                   operand *right,
10026                                   operand *result,
10027                                   iCode *ic,
10028                                   int sign)
10029 {    
10030   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10031   int lsize,res_size;
10032
10033   pic16_freeAsmop(right,NULL,ic,TRUE);
10034
10035   pic16_aopOp(left,ic,FALSE);
10036   pic16_aopOp(result,ic,TRUE);
10037
10038   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10039
10040 #if VIEW_SIZE
10041   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10042                  AOP_SIZE(left));
10043 #endif
10044
10045   lsize = pic16_getDataSize(left);
10046   res_size = pic16_getDataSize(result);
10047   /* test the LEFT size !!! */
10048
10049   /* I suppose that the left size >= result size */
10050   if(shCount == 0){
10051     assert (res_size <= lsize);
10052     while (res_size--) {
10053       pic16_mov2f (AOP(result), AOP(left), res_size);
10054     } // for
10055   }
10056
10057   else if(shCount >= (lsize * 8)){
10058
10059     if(res_size == 1) {
10060       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10061       if(sign) {
10062         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10063         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10064       }
10065     } else {
10066
10067       if(sign) {
10068         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10069         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10070         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10071         while(res_size--)
10072           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10073
10074       } else {
10075
10076         while(res_size--)
10077           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10078       }
10079     }
10080   } else {
10081
10082     switch (res_size) {
10083     case 1:
10084       genrshOne (result,left,shCount,sign);
10085       break;
10086
10087     case 2:
10088       genrshTwo (result,left,shCount,sign);
10089       break;
10090
10091     case 4:
10092       genrshFour (result,left,shCount,sign);
10093       break;
10094     default :
10095       break;
10096     }
10097
10098   }
10099
10100   pic16_freeAsmop(left,NULL,ic,TRUE);
10101   pic16_freeAsmop(result,NULL,ic,TRUE);
10102 }
10103
10104 #if !(USE_GENERIC_SIGNED_SHIFT)
10105 /*-----------------------------------------------------------------*/
10106 /* genSignedRightShift - right shift of signed number              */
10107 /*-----------------------------------------------------------------*/
10108 static void genSignedRightShift (iCode *ic)
10109 {
10110   operand *right, *left, *result;
10111   int size, offset;
10112   //  char *l;
10113   symbol *tlbl, *tlbl1 ;
10114   pCodeOp *pctemp;
10115
10116   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10117
10118   /* we do it the hard way put the shift count in b
10119      and loop thru preserving the sign */
10120   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10121
10122   right = IC_RIGHT(ic);
10123   left  = IC_LEFT(ic);
10124   result = IC_RESULT(ic);
10125
10126   pic16_aopOp(right,ic,FALSE);  
10127   pic16_aopOp(left,ic,FALSE);
10128   pic16_aopOp(result,ic,FALSE);
10129
10130
10131   if ( AOP_TYPE(right) == AOP_LIT) {
10132     genRightShiftLiteral (left,right,result,ic,1);
10133     return ;
10134   }
10135   /* shift count is unknown then we have to form 
10136      a loop get the loop count in B : Note: we take
10137      only the lower order byte since shifting
10138      more that 32 bits make no sense anyway, ( the
10139      largest size of an object can be only 32 bits ) */  
10140
10141   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10142   //pic16_emitcode("inc","b");
10143   //pic16_freeAsmop (right,NULL,ic,TRUE);
10144   //pic16_aopOp(left,ic,FALSE);
10145   //pic16_aopOp(result,ic,FALSE);
10146
10147   /* now move the left to the result if they are not the
10148      same */
10149   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10150       AOP_SIZE(result) > 1) {
10151
10152     size = AOP_SIZE(result);
10153     offset=0;
10154     while (size--) { 
10155       /*
10156         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10157         if (*l == '@' && IS_AOP_PREG(result)) {
10158
10159         pic16_emitcode("mov","a,%s",l);
10160         pic16_aopPut(AOP(result),"a",offset);
10161         } else
10162         pic16_aopPut(AOP(result),l,offset);
10163       */
10164       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10165       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10166
10167       offset++;
10168     }
10169   }
10170
10171   /* mov the highest order bit to OVR */    
10172   tlbl = newiTempLabel(NULL);
10173   tlbl1= newiTempLabel(NULL);
10174
10175   size = AOP_SIZE(result);
10176   offset = size - 1;
10177
10178   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10179
10180   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10181
10182   /* offset should be 0, 1 or 3 */
10183   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10184   emitSKPNZ;
10185   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10186
10187   pic16_emitpcode(POC_MOVWF, pctemp);
10188
10189
10190   pic16_emitpLabel(tlbl->key);
10191
10192   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10193   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10194
10195   while(--size) {
10196     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10197   }
10198
10199   pic16_emitpcode(POC_DECFSZ,  pctemp);
10200   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10201   pic16_emitpLabel(tlbl1->key);
10202
10203   pic16_popReleaseTempReg(pctemp,1);
10204 #if 0
10205   size = AOP_SIZE(result);
10206   offset = size - 1;
10207   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10208   pic16_emitcode("rlc","a");
10209   pic16_emitcode("mov","ov,c");
10210   /* if it is only one byte then */
10211   if (size == 1) {
10212     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10213     MOVA(l);
10214     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10215     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10216     pic16_emitcode("mov","c,ov");
10217     pic16_emitcode("rrc","a");
10218     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10219     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10220     pic16_aopPut(AOP(result),"a",0);
10221     goto release ;
10222   }
10223
10224   reAdjustPreg(AOP(result));
10225   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10226   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10227   pic16_emitcode("mov","c,ov");
10228   while (size--) {
10229     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10230     MOVA(l);
10231     pic16_emitcode("rrc","a");         
10232     pic16_aopPut(AOP(result),"a",offset--);
10233   }
10234   reAdjustPreg(AOP(result));
10235   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10236   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10237
10238  release:
10239 #endif
10240
10241   pic16_freeAsmop(left,NULL,ic,TRUE);
10242   pic16_freeAsmop(result,NULL,ic,TRUE);
10243   pic16_freeAsmop(right,NULL,ic,TRUE);
10244 }
10245 #endif
10246
10247 #if !(USE_GENERIC_SIGNED_SHIFT)
10248 #warning This implementation of genRightShift() is incomplete!
10249 /*-----------------------------------------------------------------*/
10250 /* genRightShift - generate code for right shifting                */
10251 /*-----------------------------------------------------------------*/
10252 static void genRightShift (iCode *ic)
10253 {
10254     operand *right, *left, *result;
10255     sym_link *letype ;
10256     int size, offset;
10257     char *l;
10258     symbol *tlbl, *tlbl1 ;
10259
10260     /* if signed then we do it the hard way preserve the
10261     sign bit moving it inwards */
10262     letype = getSpec(operandType(IC_LEFT(ic)));
10263     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10264
10265     if (!SPEC_USIGN(letype)) {
10266         genSignedRightShift (ic);
10267         return ;
10268     }
10269
10270     /* signed & unsigned types are treated the same : i.e. the
10271     signed is NOT propagated inwards : quoting from the
10272     ANSI - standard : "for E1 >> E2, is equivalent to division
10273     by 2**E2 if unsigned or if it has a non-negative value,
10274     otherwise the result is implementation defined ", MY definition
10275     is that the sign does not get propagated */
10276
10277     right = IC_RIGHT(ic);
10278     left  = IC_LEFT(ic);
10279     result = IC_RESULT(ic);
10280
10281     pic16_aopOp(right,ic,FALSE);
10282
10283     /* if the shift count is known then do it 
10284     as efficiently as possible */
10285     if (AOP_TYPE(right) == AOP_LIT) {
10286         genRightShiftLiteral (left,right,result,ic, 0);
10287         return ;
10288     }
10289
10290     /* shift count is unknown then we have to form 
10291     a loop get the loop count in B : Note: we take
10292     only the lower order byte since shifting
10293     more that 32 bits make no sense anyway, ( the
10294     largest size of an object can be only 32 bits ) */  
10295
10296     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10297     pic16_emitcode("inc","b");
10298     pic16_aopOp(left,ic,FALSE);
10299     pic16_aopOp(result,ic,FALSE);
10300
10301     /* now move the left to the result if they are not the
10302     same */
10303     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10304         AOP_SIZE(result) > 1) {
10305
10306         size = AOP_SIZE(result);
10307         offset=0;
10308         while (size--) {
10309             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10310             if (*l == '@' && IS_AOP_PREG(result)) {
10311
10312                 pic16_emitcode("mov","a,%s",l);
10313                 pic16_aopPut(AOP(result),"a",offset);
10314             } else
10315                 pic16_aopPut(AOP(result),l,offset);
10316             offset++;
10317         }
10318     }
10319
10320     tlbl = newiTempLabel(NULL);
10321     tlbl1= newiTempLabel(NULL);
10322     size = AOP_SIZE(result);
10323     offset = size - 1;
10324
10325     /* if it is only one byte then */
10326     if (size == 1) {
10327
10328       tlbl = newiTempLabel(NULL);
10329       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10330         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10331         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10332       }
10333
10334       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10335       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10336       pic16_emitpLabel(tlbl->key);
10337       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10338       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10339       emitSKPC;
10340       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10341
10342       goto release ;
10343     }
10344
10345     reAdjustPreg(AOP(result));
10346     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10347     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10348     CLRC;
10349     while (size--) {
10350         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10351         MOVA(l);
10352         pic16_emitcode("rrc","a");         
10353         pic16_aopPut(AOP(result),"a",offset--);
10354     }
10355     reAdjustPreg(AOP(result));
10356
10357     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10358     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10359
10360 release:
10361     pic16_freeAsmop(left,NULL,ic,TRUE);
10362     pic16_freeAsmop (right,NULL,ic,TRUE);
10363     pic16_freeAsmop(result,NULL,ic,TRUE);
10364 }
10365 #endif
10366
10367 #if (USE_GENERIC_SIGNED_SHIFT)
10368 /*-----------------------------------------------------------------*/
10369 /* genGenericShift - generates code for left or right shifting     */
10370 /*-----------------------------------------------------------------*/
10371 static void genGenericShift (iCode *ic, int isShiftLeft) {
10372   operand *left,*right, *result;
10373   int offset;
10374   int sign, signedCount;
10375   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10376   PIC_OPCODE pos_shift, neg_shift;
10377
10378   FENTRY;
10379
10380   right = IC_RIGHT(ic);
10381   left  = IC_LEFT(ic);
10382   result = IC_RESULT(ic);
10383
10384   pic16_aopOp(right,ic,FALSE);
10385   pic16_aopOp(left,ic,FALSE);
10386   pic16_aopOp(result,ic,TRUE);
10387
10388   sign = !SPEC_USIGN(operandType (left));
10389   signedCount = !SPEC_USIGN(operandType (right));
10390
10391   /* if the shift count is known then do it 
10392      as efficiently as possible */
10393   if (AOP_TYPE(right) == AOP_LIT) {
10394     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10395     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10396     // we should modify right->aopu.aop_lit here!
10397     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10398     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10399     if (isShiftLeft)
10400       pic16_genLeftShiftLiteral (left,right,result,ic);
10401     else
10402       genRightShiftLiteral (left,right,result,ic, sign);
10403
10404     goto release;
10405   } // if (right is literal)
10406
10407   /* shift count is unknown then we have to form a loop.
10408    * Note: we take only the lower order byte since shifting
10409    * more than 32 bits make no sense anyway, ( the
10410    * largest size of an object can be only 32 bits )
10411    * Note: we perform arithmetic shifts if the left operand is
10412    * signed and we do an (effective) right shift, i. e. we
10413    * shift in the sign bit from the left. */
10414    
10415   label_complete = newiTempLabel ( NULL );
10416   label_loop_pos = newiTempLabel ( NULL );
10417   label_loop_neg = NULL;
10418   label_negative = NULL;
10419   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10420   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10421
10422   if (signedCount) {
10423     // additional labels needed
10424     label_loop_neg = newiTempLabel ( NULL );
10425     label_negative = newiTempLabel ( NULL );
10426   } // if
10427
10428   // copy source to result -- this will effectively truncate the left operand to the size of result!
10429   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10430   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10431   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10432     pic16_mov2f (AOP(result),AOP(left), offset);
10433   } // for
10434
10435   // if result is longer than left, fill with zeros (or sign)
10436   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10437     if (sign && AOP_SIZE(left) > 0) {
10438       // shift signed operand -- fill with sign
10439       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10440       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10441       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10442       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10443         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10444       } // for
10445     } else {
10446       // shift unsigned operand -- fill result with zeros
10447       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10448         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10449       } // for
10450     }
10451   } // if (size mismatch)
10452
10453   pic16_mov2w (AOP(right), 0);
10454   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10455   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10456   
10457 #if 0
10458   // perform a shift by one (shift count is positive)
10459   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10460   // 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])
10461   pic16_emitpLabel (label_loop_pos->key);
10462   emitCLRC;
10463   if (sign && (pos_shift == POC_RRCF)) {
10464     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10465     emitSETC;
10466   } // if
10467   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10468   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10469   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10470 #else
10471   // perform a shift by one (shift count is positive)
10472   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10473   // 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])
10474   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10475   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10476   emitCLRC;
10477   pic16_emitpLabel (label_loop_pos->key);
10478   if (sign && (pos_shift == POC_RRCF)) {
10479     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10480     emitSETC;
10481   } // if
10482   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10483   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10484   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10485   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10486 #endif
10487
10488   if (signedCount) {
10489     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10490
10491     pic16_emitpLabel (label_negative->key);
10492     // perform a shift by -1 (shift count is negative)
10493     // 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)
10494     emitCLRC;
10495     pic16_emitpLabel (label_loop_neg->key);
10496     if (sign && (neg_shift == POC_RRCF)) {
10497       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10498       emitSETC;
10499     } // if
10500     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10501     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10502     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10503     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10504   } // if (signedCount)
10505
10506   pic16_emitpLabel (label_complete->key);
10507
10508 release:
10509   pic16_freeAsmop (right,NULL,ic,TRUE);
10510   pic16_freeAsmop(left,NULL,ic,TRUE);
10511   pic16_freeAsmop(result,NULL,ic,TRUE);
10512 }
10513
10514 static void genLeftShift (iCode *ic) {
10515   genGenericShift (ic, 1);
10516 }
10517
10518 static void genRightShift (iCode *ic) {
10519   genGenericShift (ic, 0);
10520 }
10521 #endif
10522
10523
10524 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10525 void pic16_loadFSR0(operand *op, int lit)
10526 {
10527   if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10528     pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10529   } else {
10530     assert (!OP_SYMBOL(op)->remat);
10531     // set up FSR0 with address of result
10532     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10533     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10534   }
10535 }
10536
10537 /*----------------------------------------------------------------*/
10538 /* pic16_derefPtr - move one byte from the location ptr points to */
10539 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10540 /*                  to the location ptr points to (doWrite != 0)   */
10541 /*----------------------------------------------------------------*/
10542 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10543 {
10544   switch (p_type) {
10545     case FPOINTER:
10546     case POINTER:
10547       if (!fsr0_setup || !*fsr0_setup)
10548       {
10549         pic16_loadFSR0( ptr, 0 );
10550         if (fsr0_setup) *fsr0_setup = 1;
10551       }
10552       if (doWrite)
10553         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10554       else
10555         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10556       break;
10557
10558     case GPOINTER:
10559       if (AOP(ptr)->aopu.aop_reg[2]) {
10560         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10561         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10562         pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10563         pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),1), pic16_popCopyReg(&pic16_pc_prodl)));
10564         pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(ptr),2));
10565         pic16_callGenericPointerRW(doWrite, 1);
10566       } else {
10567         // data pointer (just 2 byte given)
10568         if (!fsr0_setup || !*fsr0_setup)
10569         {
10570           pic16_loadFSR0( ptr, 0 );
10571           if (fsr0_setup) *fsr0_setup = 1;
10572         }
10573         if (doWrite)
10574           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10575         else
10576           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10577       }
10578       break;
10579
10580     default:
10581       assert (0 && "invalid pointer type specified");
10582       break;
10583   }
10584 }
10585
10586 /*-----------------------------------------------------------------*/
10587 /* genUnpackBits - generates code for unpacking bits               */
10588 /*-----------------------------------------------------------------*/
10589 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10590 {    
10591   int shCnt ;
10592   sym_link *etype, *letype;
10593   int blen=0, bstr=0;
10594   int lbstr;
10595
10596     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10597     etype = getSpec(operandType(result));
10598     letype = getSpec(operandType(left));
10599     
10600 //    if(IS_BITFIELD(etype)) {
10601       blen = SPEC_BLEN(etype);
10602       bstr = SPEC_BSTR(etype);
10603 //    }
10604
10605     lbstr = SPEC_BSTR( letype );
10606
10607 #if 1
10608     if((blen == 1) && (bstr < 8)) {
10609       /* it is a single bit, so use the appropriate bit instructions */
10610       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10611
10612       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10613       
10614       // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10615       if(!IS_PTR(operandType(left))/* && OP_SYMBOL(left)->remat && (ptype == POINTER)*/) {
10616         /* workaround to reduce the extra lfsr instruction */
10617         pic16_emitpcode(POC_BTFSC,
10618               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10619       } else {
10620         pic16_loadFSR0 (left, 0);
10621         pic16_emitpcode(POC_BTFSC,
10622               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10623       }
10624         
10625       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10626
10627       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10628       return;
10629     }
10630
10631 #endif
10632
10633         /* the following call to pic16_loadFSR0 is temporary until
10634          * optimization to handle single bit assignments is added
10635          * to the function. Until then use the old safe way! -- VR */
10636
10637     if (!IS_PTR(operandType(left)) /*OP_SYMBOL(left)->remat*/) {
10638         // access symbol directly
10639         pic16_mov2w (AOP(left), 0);
10640     } else {
10641       pic16_derefPtr (left, ptype, 0, NULL);
10642     }
10643
10644         /* if we have bitdisplacement then it fits   */
10645         /* into this byte completely or if length is */
10646         /* less than a byte                          */
10647         if ((shCnt = SPEC_BSTR(etype)) || 
10648                 (SPEC_BLEN(etype) <= 8))  {
10649
10650                 /* shift right acc */
10651                 AccRsh(shCnt, 0);
10652
10653                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10654                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10655
10656 /* VR -- normally I would use the following, but since we use the hack,
10657  * to avoid the masking from AccRsh, why not mask it right now? */
10658
10659 /*
10660                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10661 */
10662
10663                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10664           return ;
10665         }
10666
10667
10668
10669         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10670         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10671         exit(-1);
10672
10673     return ;
10674 }
10675
10676
10677 static void genDataPointerGet(operand *left,
10678                               operand *result,
10679                               iCode *ic)
10680 {
10681   int size, offset = 0, leoffset=0 ;
10682
10683         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10684         pic16_aopOp(result, ic, TRUE);
10685
10686         FENTRY;
10687
10688         size = AOP_SIZE(result);
10689 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10690
10691
10692 #if 0
10693         /* The following tests may save a redudant movff instruction when
10694          * accessing unions */
10695          
10696         /* if they are the same */
10697         if (operandsEqu (left, result)) {
10698                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10699                 goto release;
10700         }
10701 #endif
10702
10703 #if 0
10704         /* if they are the same registers */
10705         if (pic16_sameRegs(AOP(left),AOP(result))) {
10706                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10707                 goto release;
10708         }
10709 #endif
10710
10711 #if 1
10712         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10713                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10714                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10715                 goto release;
10716         }
10717 #endif
10718
10719
10720 #if 0
10721         if ( AOP_TYPE(left) == AOP_PCODE) {
10722                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
10723                                 AOP(left)->aopu.pcop->name,
10724                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
10725                                 PCOR(AOP(left)->aopu.pcop)->instance:
10726                                 PCOI(AOP(left)->aopu.pcop)->offset);
10727         }
10728 #endif
10729
10730         if(AOP(left)->aopu.pcop->type == PO_DIR)
10731                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10732
10733         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10734
10735         while (size--) {
10736                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10737                 
10738 //              pic16_DumpOp("(result)",result);
10739                 if(is_LitAOp(AOP(result))) {
10740                         pic16_mov2w(AOP(left), offset); // patch 8
10741                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10742                 } else {
10743                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10744                                 pic16_popGet(AOP(left), offset), //patch 8
10745                                 pic16_popGet(AOP(result), offset)));
10746                 }
10747
10748                 offset++;
10749                 leoffset++;
10750         }
10751
10752 release:
10753     pic16_freeAsmop(result,NULL,ic,TRUE);
10754 }
10755
10756
10757
10758 /*-----------------------------------------------------------------*/
10759 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10760 /*-----------------------------------------------------------------*/
10761 static void genNearPointerGet (operand *left, 
10762                                operand *result, 
10763                                iCode *ic)
10764 {
10765 //  asmop *aop = NULL;
10766   //regs *preg = NULL ;
10767   sym_link *rtype, *retype;
10768   sym_link *ltype, *letype;
10769
10770     FENTRY;
10771     
10772     rtype = operandType(result);
10773     retype= getSpec(rtype);
10774     ltype = operandType(left);
10775     letype= getSpec(ltype);
10776     
10777     pic16_aopOp(left,ic,FALSE);
10778
10779 //    pic16_DumpOp("(left)",left);
10780 //    pic16_DumpOp("(result)",result);
10781
10782     /* if left is rematerialisable and
10783      * result is not bit variable type and
10784      * the left is pointer to data space i.e
10785      * lower 128 bytes of space */
10786     
10787     if (AOP_TYPE(left) == AOP_PCODE
10788       && !IS_BITFIELD(retype)
10789       && DCL_TYPE(ltype) == POINTER) {
10790
10791         genDataPointerGet (left,result,ic);
10792         pic16_freeAsmop(left, NULL, ic, TRUE);
10793         return ;
10794     }
10795     
10796     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10797     pic16_aopOp (result,ic,TRUE);
10798     
10799     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10800
10801 #if 1
10802     if(IS_BITFIELD( retype )
10803       && (SPEC_BLEN(operandType(result))==1)
10804     ) {
10805       iCode *nextic;
10806       pCodeOp *jop;
10807       int bitstrt, bytestrt;
10808
10809         /* if this is bitfield of size 1, see if we are checking the value
10810          * of a single bit in an if-statement,
10811          * if yes, then don't generate usual code, but execute the
10812          * genIfx directly -- VR */
10813
10814         nextic = ic->next;
10815
10816         /* CHECK: if next iCode is IFX
10817          * and current result operand is nextic's conditional operand
10818          * and current result operand live ranges ends at nextic's key number
10819          */
10820         if((nextic->op == IFX)
10821           && (result == IC_COND(nextic))
10822           && (OP_LIVETO(result) == nextic->seq)
10823           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10824           ) {
10825             /* everything is ok then */
10826             /* find a way to optimize the genIfx iCode */
10827
10828             bytestrt = SPEC_BSTR(operandType(result))/8;
10829             bitstrt = SPEC_BSTR(operandType(result))%8;
10830             
10831             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10832
10833             genIfxpCOpJump(nextic, jop);
10834             
10835             pic16_freeAsmop(left, NULL, ic, TRUE);
10836             pic16_freeAsmop(result, NULL, ic, TRUE);
10837             return;
10838         }
10839     }
10840 #endif
10841
10842     /* if bitfield then unpack the bits */
10843     if (IS_BITFIELD(letype)) 
10844       genUnpackBits (result, left, NULL, POINTER);
10845     else {
10846       /* we have can just get the values */
10847       int size = AOP_SIZE(result);
10848       int offset = 0;   
10849         
10850       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10851
10852       pic16_loadFSR0( left, 0 );
10853
10854       while(size--) {
10855         if(size) {
10856           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10857                 pic16_popGet(AOP(result), offset++)));
10858         } else {
10859           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10860                 pic16_popGet(AOP(result), offset++)));
10861         }
10862       }
10863     }
10864
10865 #if 0
10866     /* now some housekeeping stuff */
10867     if (aop) {
10868       /* we had to allocate for this iCode */
10869       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10870       pic16_freeAsmop(NULL,aop,ic,TRUE);
10871     } else { 
10872       /* we did not allocate which means left
10873        * already in a pointer register, then
10874        * if size > 0 && this could be used again
10875        * we have to point it back to where it 
10876        * belongs */
10877       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10878       if (AOP_SIZE(result) > 1
10879         && !OP_SYMBOL(left)->remat
10880         && ( OP_SYMBOL(left)->liveTo > ic->seq
10881             || ic->depth )) {
10882 //        int size = AOP_SIZE(result) - 1;
10883 //        while (size--)
10884 //          pic16_emitcode("dec","%s",rname);
10885         }
10886     }
10887 #endif
10888
10889     /* done */
10890     pic16_freeAsmop(left,NULL,ic,TRUE);
10891     pic16_freeAsmop(result,NULL,ic,TRUE);
10892 }
10893
10894 /*-----------------------------------------------------------------*/
10895 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10896 /*-----------------------------------------------------------------*/
10897 static void genPagedPointerGet (operand *left, 
10898                                operand *result, 
10899                                iCode *ic)
10900 {
10901     asmop *aop = NULL;
10902     regs *preg = NULL ;
10903     char *rname ;
10904     sym_link *rtype, *retype;    
10905
10906     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10907
10908     rtype = operandType(result);
10909     retype= getSpec(rtype);
10910     
10911     pic16_aopOp(left,ic,FALSE);
10912
10913   /* if the value is already in a pointer register
10914        then don't need anything more */
10915     if (!AOP_INPREG(AOP(left))) {
10916         /* otherwise get a free pointer register */
10917         aop = newAsmop(0);
10918         preg = getFreePtr(ic,&aop,FALSE);
10919         pic16_emitcode("mov","%s,%s",
10920                 preg->name,
10921                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10922         rname = preg->name ;
10923     } else
10924         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10925     
10926     pic16_freeAsmop(left,NULL,ic,TRUE);
10927     pic16_aopOp (result,ic,TRUE);
10928
10929     /* if bitfield then unpack the bits */
10930     if (IS_BITFIELD(retype)) 
10931         genUnpackBits (result,left,rname,PPOINTER);
10932     else {
10933         /* we have can just get the values */
10934         int size = AOP_SIZE(result);
10935         int offset = 0 ;        
10936         
10937         while (size--) {
10938             
10939             pic16_emitcode("movx","a,@%s",rname);
10940             pic16_aopPut(AOP(result),"a",offset);
10941             
10942             offset++ ;
10943             
10944             if (size)
10945                 pic16_emitcode("inc","%s",rname);
10946         }
10947     }
10948
10949     /* now some housekeeping stuff */
10950     if (aop) {
10951         /* we had to allocate for this iCode */
10952         pic16_freeAsmop(NULL,aop,ic,TRUE);
10953     } else { 
10954         /* we did not allocate which means left
10955            already in a pointer register, then
10956            if size > 0 && this could be used again
10957            we have to point it back to where it 
10958            belongs */
10959         if (AOP_SIZE(result) > 1 &&
10960             !OP_SYMBOL(left)->remat &&
10961             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10962               ic->depth )) {
10963             int size = AOP_SIZE(result) - 1;
10964             while (size--)
10965                 pic16_emitcode("dec","%s",rname);
10966         }
10967     }
10968
10969     /* done */
10970     pic16_freeAsmop(result,NULL,ic,TRUE);
10971     
10972         
10973 }
10974
10975 /*-----------------------------------------------------------------*/
10976 /* genFarPointerGet - gget value from far space                    */
10977 /*-----------------------------------------------------------------*/
10978 static void genFarPointerGet (operand *left,
10979                               operand *result, iCode *ic)
10980 {
10981     int size, offset ;
10982     sym_link *retype = getSpec(operandType(result));
10983
10984     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10985
10986     pic16_aopOp(left,ic,FALSE);
10987
10988     /* if the operand is already in dptr 
10989     then we do nothing else we move the value to dptr */
10990     if (AOP_TYPE(left) != AOP_STR) {
10991         /* if this is remateriazable */
10992         if (AOP_TYPE(left) == AOP_IMMD)
10993             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10994         else { /* we need to get it byte by byte */
10995             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10996             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10997             if (options.model == MODEL_FLAT24)
10998             {
10999                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11000             }
11001         }
11002     }
11003     /* so dptr know contains the address */
11004     pic16_freeAsmop(left,NULL,ic,TRUE);
11005     pic16_aopOp(result,ic,TRUE);
11006
11007     /* if bit then unpack */
11008     if (IS_BITFIELD(retype)) 
11009         genUnpackBits(result,left,"dptr",FPOINTER);
11010     else {
11011         size = AOP_SIZE(result);
11012         offset = 0 ;
11013
11014         while (size--) {
11015             pic16_emitcode("movx","a,@dptr");
11016             pic16_aopPut(AOP(result),"a",offset++);
11017             if (size)
11018                 pic16_emitcode("inc","dptr");
11019         }
11020     }
11021
11022     pic16_freeAsmop(result,NULL,ic,TRUE);
11023 }
11024
11025 #if 0
11026 /*-----------------------------------------------------------------*/
11027 /* genCodePointerGet - get value from code space                  */
11028 /*-----------------------------------------------------------------*/
11029 static void genCodePointerGet (operand *left,
11030                                 operand *result, iCode *ic)
11031 {
11032     int size, offset ;
11033     sym_link *retype = getSpec(operandType(result));
11034
11035     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11036
11037     pic16_aopOp(left,ic,FALSE);
11038
11039     /* if the operand is already in dptr 
11040     then we do nothing else we move the value to dptr */
11041     if (AOP_TYPE(left) != AOP_STR) {
11042         /* if this is remateriazable */
11043         if (AOP_TYPE(left) == AOP_IMMD)
11044             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11045         else { /* we need to get it byte by byte */
11046             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11047             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11048             if (options.model == MODEL_FLAT24)
11049             {
11050                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11051             }
11052         }
11053     }
11054     /* so dptr know contains the address */
11055     pic16_freeAsmop(left,NULL,ic,TRUE);
11056     pic16_aopOp(result,ic,FALSE);
11057
11058     /* if bit then unpack */
11059     if (IS_BITFIELD(retype)) 
11060         genUnpackBits(result,left,"dptr",CPOINTER);
11061     else {
11062         size = AOP_SIZE(result);
11063         offset = 0 ;
11064
11065         while (size--) {
11066             pic16_emitcode("clr","a");
11067             pic16_emitcode("movc","a,@a+dptr");
11068             pic16_aopPut(AOP(result),"a",offset++);
11069             if (size)
11070                 pic16_emitcode("inc","dptr");
11071         }
11072     }
11073
11074     pic16_freeAsmop(result,NULL,ic,TRUE);
11075 }
11076 #endif
11077
11078 #if 0
11079 /*-----------------------------------------------------------------*/
11080 /* genGenPointerGet - gget value from generic pointer space        */
11081 /*-----------------------------------------------------------------*/
11082 static void genGenPointerGet (operand *left,
11083                               operand *result, iCode *ic)
11084 {
11085   int size, offset, lit;
11086   sym_link *retype = getSpec(operandType(result));
11087
11088         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11089         pic16_aopOp(left,ic,FALSE);
11090         pic16_aopOp(result,ic,FALSE);
11091         size = AOP_SIZE(result);
11092
11093         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11094
11095         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11096
11097                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11098                 // load FSR0 from immediate
11099                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11100
11101 //              pic16_loadFSR0( left );
11102
11103                 offset = 0;
11104                 while(size--) {
11105                         if(size) {
11106                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11107                         } else {
11108                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11109                         }
11110                         offset++;
11111                 }
11112                 goto release;
11113
11114         }
11115         else { /* we need to get it byte by byte */
11116                 // set up FSR0 with address from left
11117                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11118                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11119                 
11120                 offset = 0 ;
11121
11122                 while(size--) {
11123                         if(size) {
11124                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11125                         } else {
11126                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11127                         }
11128                         offset++;
11129                 }
11130                 goto release;
11131         }
11132
11133   /* if bit then unpack */
11134         if (IS_BITFIELD(retype)) 
11135                 genUnpackBits(result,left,"BAD",GPOINTER);
11136
11137         release:
11138         pic16_freeAsmop(left,NULL,ic,TRUE);
11139         pic16_freeAsmop(result,NULL,ic,TRUE);
11140
11141 }
11142 #endif
11143
11144
11145 /*-----------------------------------------------------------------*/
11146 /* genGenPointerGet - gget value from generic pointer space        */
11147 /*-----------------------------------------------------------------*/
11148 static void genGenPointerGet (operand *left,
11149                               operand *result, iCode *ic)
11150 {
11151   int size, offset, lit;
11152   sym_link *letype = getSpec(operandType(left));
11153
11154     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11155     pic16_aopOp(left,ic,FALSE);
11156     pic16_aopOp(result,ic,TRUE);
11157     size = AOP_SIZE(result);
11158
11159     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11160   
11161     /* if bit then unpack */
11162     if (IS_BITFIELD(letype)) {
11163       genUnpackBits(result,left,"BAD",GPOINTER);
11164       goto release;
11165     }
11166
11167     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11168
11169       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11170       // load FSR0 from immediate
11171       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11172
11173       werror(W_POSSBUG2, __FILE__, __LINE__);
11174
11175       offset = 0;
11176       while(size--) {
11177         if(size) {
11178           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11179         } else {
11180           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11181         }
11182         offset++;
11183       }
11184
11185       goto release;
11186
11187     } else { /* we need to get it byte by byte */
11188
11189       /* set up WREG:PRODL:FSR0L with address from left */
11190       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11191       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11192       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11193       
11194       pic16_callGenericPointerRW(0, size);
11195       
11196       assignResultValue(result, 1);
11197       
11198       goto release;
11199     }
11200
11201 release:
11202   pic16_freeAsmop(left,NULL,ic,TRUE);
11203   pic16_freeAsmop(result,NULL,ic,TRUE);
11204 }
11205
11206 /*-----------------------------------------------------------------*/
11207 /* genConstPointerGet - get value from const generic pointer space */
11208 /*-----------------------------------------------------------------*/
11209 static void genConstPointerGet (operand *left,
11210                                 operand *result, iCode *ic)
11211 {
11212   //sym_link *retype = getSpec(operandType(result));
11213   // symbol *albl = newiTempLabel(NULL);        // patch 15
11214   // symbol *blbl = newiTempLabel(NULL);        //
11215   // PIC_OPCODE poc;                            // patch 15
11216   int size;
11217   int offset = 0;
11218
11219   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11220   pic16_aopOp(left,ic,FALSE);
11221   pic16_aopOp(result,ic,TRUE);
11222   size = AOP_SIZE(result);
11223
11224   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11225
11226   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11227
11228   // set up table pointer
11229   if( (AOP_TYPE(left) == AOP_PCODE) 
11230       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11231           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11232     {
11233       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11234       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11235       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11236       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11237       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11238       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11239   } else {
11240     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11241     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11242     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11243   }
11244
11245   while(size--) {
11246     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11247     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11248     offset++;
11249   }
11250     
11251   pic16_freeAsmop(left,NULL,ic,TRUE);
11252   pic16_freeAsmop(result,NULL,ic,TRUE);
11253 }
11254
11255
11256 /*-----------------------------------------------------------------*/
11257 /* genPointerGet - generate code for pointer get                   */
11258 /*-----------------------------------------------------------------*/
11259 static void genPointerGet (iCode *ic)
11260 {
11261   operand *left, *result ;
11262   sym_link *type, *etype;
11263   int p_type;
11264
11265     FENTRY;
11266     
11267     left = IC_LEFT(ic);
11268     result = IC_RESULT(ic) ;
11269
11270     /* depending on the type of pointer we need to
11271     move it to the correct pointer register */
11272     type = operandType(left);
11273     etype = getSpec(type);
11274
11275 #if 0
11276     if (IS_PTR_CONST(type))
11277 #else
11278     if (IS_CODEPTR(type))
11279 #endif
11280       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11281
11282     /* if left is of type of pointer then it is simple */
11283     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11284       p_type = DCL_TYPE(type);
11285     else {
11286       /* we have to go by the storage class */
11287       p_type = PTR_TYPE(SPEC_OCLS(etype));
11288
11289       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11290
11291       if (SPEC_OCLS(etype)->codesp ) {
11292         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11293         //p_type = CPOINTER ;   
11294       } else
11295       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11296         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11297         /*p_type = FPOINTER ;*/ 
11298       } else
11299       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11300         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11301         /* p_type = PPOINTER; */
11302       } else
11303       if (SPEC_OCLS(etype) == idata ) {
11304         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11305         /* p_type = IPOINTER; */
11306       } else {
11307         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11308         /* p_type = POINTER ; */
11309       }
11310     }
11311
11312     /* now that we have the pointer type we assign
11313     the pointer values */
11314     switch (p_type) {
11315       case POINTER:     
11316       case IPOINTER:
11317         genNearPointerGet (left,result,ic);
11318         break;
11319
11320       case PPOINTER:
11321         genPagedPointerGet(left,result,ic);
11322         break;
11323
11324       case FPOINTER:
11325         genFarPointerGet (left,result,ic);
11326         break;
11327
11328       case CPOINTER:
11329         genConstPointerGet (left,result,ic);
11330         //pic16_emitcodePointerGet (left,result,ic);
11331         break;
11332
11333       case GPOINTER:
11334 #if 0
11335       if (IS_PTR_CONST(type))
11336         genConstPointerGet (left,result,ic);
11337       else
11338 #endif
11339         genGenPointerGet (left,result,ic);
11340       break;
11341
11342     default:
11343       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11344               "genPointerGet: illegal pointer type");
11345     
11346     }
11347 }
11348
11349 /*-----------------------------------------------------------------*/
11350 /* genPackBits - generates code for packed bit storage             */
11351 /*-----------------------------------------------------------------*/
11352 static void genPackBits (sym_link    *etype , operand *result,
11353                          operand *right ,
11354                          char *rname, int p_type)
11355 {
11356   int shCnt = 0 ;
11357   int offset = 0  ;
11358   int rLen = 0 ;
11359   int blen, bstr ;   
11360   sym_link *retype;
11361
11362         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11363         blen = SPEC_BLEN(etype);
11364         bstr = SPEC_BSTR(etype);
11365
11366         retype = getSpec(operandType(right));
11367
11368         if(AOP_TYPE(right) == AOP_LIT) {
11369                 if((blen == 1) && (bstr < 8)) {
11370                   unsigned long lit;
11371                         /* it is a single bit, so use the appropriate bit instructions */
11372
11373                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11374
11375                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11376 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11377                         if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11378                                 /* workaround to reduce the extra lfsr instruction */
11379                                 if(lit) {
11380                                         pic16_emitpcode(POC_BSF,
11381                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11382                                 } else {
11383                                         pic16_emitpcode(POC_BCF,
11384                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11385                                 }
11386                         } else {
11387                                 pic16_loadFSR0(result, 0);
11388                                 if(lit) {
11389                                         pic16_emitpcode(POC_BSF,
11390                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11391                                 } else {
11392                                         pic16_emitpcode(POC_BCF,
11393                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11394                                 }
11395                         }
11396         
11397                   return;
11398                 }
11399                 /* move literal to W */
11400                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11401                 offset++;
11402         } else
11403         if(IS_BITFIELD(retype) 
11404           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11405           && (blen == 1)) {
11406           int rblen, rbstr;
11407
11408             rblen = SPEC_BLEN( retype );
11409             rbstr = SPEC_BSTR( retype );
11410             
11411
11412             if(IS_BITFIELD(etype)) {
11413               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11414               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11415             } else {
11416               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11417             }
11418             
11419             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11420             
11421             if(IS_BITFIELD(etype)) {
11422               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11423             } else {
11424               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11425             }
11426
11427             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11428             
11429             return;
11430         } else {
11431           /* move right to W */
11432           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11433         }
11434
11435         /* if the bit length is less than or   */
11436         /* it exactly fits a byte then         */
11437         if((shCnt=SPEC_BSTR(etype))
11438                 || SPEC_BLEN(etype) <= 8 )  {
11439                 int fsr0_setup = 0;
11440
11441                 if (blen != 8 || bstr != 0) {
11442                   // we need to combine the value with the old value
11443                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11444
11445           DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11446                 SPEC_BSTR(etype), SPEC_BLEN(etype));
11447                 
11448                   /* shift left acc */
11449                   AccLsh(shCnt);
11450
11451                   /* using PRODH as a temporary register here */
11452                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11453
11454                   if (IS_SYMOP(result) && !IS_PTR(operandType (result))/*OP_SYMBOL(result)->remat*/) {
11455                     /* access symbol directly */
11456                     pic16_mov2w (AOP(result), 0);
11457                   } else {
11458                     /* get old value */
11459                     pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11460                   }
11461 #if 1
11462                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11463                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11464                                         (unsigned char)(0xff >> (8-bstr))) ));
11465                   pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11466                 } // if (blen != 8 || bstr != 0)
11467
11468                 /* write new value back */
11469                 if (IS_SYMOP(result) & !IS_PTR(operandType(result))) {
11470                   pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11471                 } else {
11472                   pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11473                }
11474 #endif
11475
11476           return;
11477         }
11478
11479
11480 #if 0
11481         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11482         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11483         exit(-1);
11484 #endif
11485
11486
11487     pic16_loadFSR0(result, 0);                  // load FSR0 with address of result
11488     rLen = SPEC_BLEN(etype)-8;
11489     
11490     /* now generate for lengths greater than one byte */
11491     while (1) {
11492         rLen -= 8 ;
11493         if (rLen <= 0 ) {
11494           mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11495           break ;
11496         }
11497
11498         switch (p_type) {
11499             case POINTER:
11500                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11501                 break;
11502
11503 /*
11504             case FPOINTER:
11505                 MOVA(l);
11506                 pic16_emitcode("movx","@dptr,a");
11507                 break;
11508
11509             case GPOINTER:
11510                 MOVA(l);
11511                 DEBUGpic16_emitcode(";lcall","__gptrput");
11512                 break;  
11513 */
11514           default:
11515             assert(0);
11516         }   
11517
11518
11519         pic16_mov2w(AOP(right), offset++);
11520     }
11521
11522     /* last last was not complete */
11523     if (rLen)   {
11524         /* save the byte & read byte */
11525         switch (p_type) {
11526             case POINTER:
11527 //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11528                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11529                 break;
11530
11531 /*
11532             case FPOINTER:
11533                 pic16_emitcode ("mov","b,a");
11534                 pic16_emitcode("movx","a,@dptr");
11535                 break;
11536
11537             case GPOINTER:
11538                 pic16_emitcode ("push","b");
11539                 pic16_emitcode ("push","acc");
11540                 pic16_emitcode ("lcall","__gptrget");
11541                 pic16_emitcode ("pop","b");
11542                 break;
11543 */
11544             default:
11545               assert(0);
11546         }
11547         DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11548         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11549         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11550 //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11551 //        pic16_emitcode ("orl","a,b");
11552     }
11553
11554 //    if (p_type == GPOINTER)
11555 //        pic16_emitcode("pop","b");
11556
11557     switch (p_type) {
11558
11559       case POINTER:
11560         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11561 //      pic16_emitcode("mov","@%s,a",rname);
11562         break;
11563 /*
11564       case FPOINTER:
11565         pic16_emitcode("movx","@dptr,a");
11566         break;
11567         
11568       case GPOINTER:
11569         DEBUGpic16_emitcode(";lcall","__gptrput");
11570         break;                  
11571 */
11572       default:
11573         assert(0);
11574     }
11575     
11576 //    pic16_freeAsmop(right, NULL, ic, TRUE);
11577 }
11578 /*-----------------------------------------------------------------*/
11579 /* genDataPointerSet - remat pointer to data space                 */
11580 /*-----------------------------------------------------------------*/
11581 static void genDataPointerSet(operand *right,
11582                               operand *result,
11583                               iCode *ic)
11584 {
11585     int size, offset = 0, resoffset=0 ;
11586
11587     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11588     pic16_aopOp(right,ic,FALSE);
11589
11590     size = AOP_SIZE(right);
11591
11592 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11593
11594 #if 0
11595     if ( AOP_TYPE(result) == AOP_PCODE) {
11596       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11597               AOP(result)->aopu.pcop->name,
11598                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11599               PCOR(AOP(result)->aopu.pcop)->instance:
11600               PCOI(AOP(result)->aopu.pcop)->offset);
11601     }
11602 #endif
11603
11604         if(AOP(result)->aopu.pcop->type == PO_DIR)
11605                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11606
11607         while (size--) {
11608                 if (AOP_TYPE(right) == AOP_LIT) {
11609                   unsigned int lit;
11610
11611                     if(!IS_FLOAT(operandType( right )))
11612                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11613                     else {
11614                       union {
11615                         unsigned long lit_int;
11616                         float lit_float;
11617                       } info;
11618         
11619                         /* take care if literal is a float */
11620                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11621                         lit = info.lit_int;
11622                     }
11623
11624                     lit = lit >> (8*offset);
11625                     if(lit&0xff) {
11626                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11627                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11628                     } else {
11629                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11630                     }
11631                 } else {
11632                   pic16_mov2w(AOP(right), offset);
11633                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11634                 }
11635                 offset++;
11636                 resoffset++;
11637         }
11638
11639     pic16_freeAsmop(right,NULL,ic,TRUE);
11640 }
11641
11642
11643
11644 /*-----------------------------------------------------------------*/
11645 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11646 /*-----------------------------------------------------------------*/
11647 static void genNearPointerSet (operand *right,
11648                                operand *result, 
11649                                iCode *ic)
11650 {
11651   asmop *aop = NULL;
11652   sym_link *retype;
11653   sym_link *ptype = operandType(result);
11654   sym_link *resetype;
11655     
11656         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11657         retype= getSpec(operandType(right));
11658         resetype = getSpec(operandType(result));
11659   
11660         pic16_aopOp(result,ic,FALSE);
11661     
11662         /* if the result is rematerializable &
11663          * in data space & not a bit variable */
11664         
11665         /* and result is not a bit variable */
11666         if (AOP_TYPE(result) == AOP_PCODE
11667 //              && AOP_TYPE(result) == AOP_IMMD
11668                 && DCL_TYPE(ptype) == POINTER
11669                 && !IS_BITFIELD(retype)
11670                 && !IS_BITFIELD(resetype)) {
11671
11672                 genDataPointerSet (right,result,ic);
11673                 pic16_freeAsmop(result,NULL,ic,TRUE);
11674           return;
11675         }
11676
11677         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11678         pic16_aopOp(right,ic,FALSE);
11679         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11680
11681         /* if bitfield then unpack the bits */
11682         if (IS_BITFIELD(resetype)) {
11683                 genPackBits (resetype, result, right, NULL, POINTER);
11684         } else {
11685                 /* we have can just get the values */
11686           int size = AOP_SIZE(right);
11687           int offset = 0 ;    
11688
11689             pic16_loadFSR0(result, 0);
11690             
11691                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11692                 while (size--) {
11693                                 if (AOP_TYPE(right) == AOP_LIT) {
11694                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11695                                         if (size) {
11696                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11697                                         } else {
11698                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11699                                         }
11700                                 } else { // no literal
11701                                         if(size) {
11702                                                 pic16_emitpcode(POC_MOVFF,
11703                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11704                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11705                                         } else {
11706                                                 pic16_emitpcode(POC_MOVFF,
11707                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11708                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11709                                         }
11710                                 }
11711                         offset++;
11712                 }
11713         }
11714
11715         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11716         /* now some housekeeping stuff */
11717         if (aop) {
11718           /* we had to allocate for this iCode */
11719           pic16_freeAsmop(NULL,aop,ic,TRUE);
11720         } else { 
11721           /* we did not allocate which means left
11722            * already in a pointer register, then
11723            * if size > 0 && this could be used again
11724            * we have to point it back to where it 
11725            * belongs */
11726           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11727           if (AOP_SIZE(right) > 1
11728             && !OP_SYMBOL(result)->remat
11729             && ( OP_SYMBOL(result)->liveTo > ic->seq
11730             || ic->depth )) {
11731
11732               int size = AOP_SIZE(right) - 1;
11733
11734                 while (size--)
11735                   pic16_emitcode("decf","fsr0,f");
11736                   //pic16_emitcode("dec","%s",rname);
11737             }
11738         }
11739
11740     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11741     /* done */
11742 //release:
11743     pic16_freeAsmop(right,NULL,ic,TRUE);
11744     pic16_freeAsmop(result,NULL,ic,TRUE);
11745 }
11746
11747 /*-----------------------------------------------------------------*/
11748 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11749 /*-----------------------------------------------------------------*/
11750 static void genPagedPointerSet (operand *right,
11751                                operand *result, 
11752                                iCode *ic)
11753 {
11754     asmop *aop = NULL;
11755     regs *preg = NULL ;
11756     char *rname , *l;
11757     sym_link *retype;
11758        
11759     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11760
11761     retype= getSpec(operandType(right));
11762     
11763     pic16_aopOp(result,ic,FALSE);
11764     
11765     /* if the value is already in a pointer register
11766        then don't need anything more */
11767     if (!AOP_INPREG(AOP(result))) {
11768         /* otherwise get a free pointer register */
11769         aop = newAsmop(0);
11770         preg = getFreePtr(ic,&aop,FALSE);
11771         pic16_emitcode("mov","%s,%s",
11772                 preg->name,
11773                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11774         rname = preg->name ;
11775     } else
11776         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11777     
11778     pic16_freeAsmop(result,NULL,ic,TRUE);
11779     pic16_aopOp (right,ic,FALSE);
11780
11781     /* if bitfield then unpack the bits */
11782     if (IS_BITFIELD(retype)) 
11783         genPackBits (retype,result,right,rname,PPOINTER);
11784     else {
11785         /* we have can just get the values */
11786         int size = AOP_SIZE(right);
11787         int offset = 0 ;        
11788         
11789         while (size--) {
11790             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11791             
11792             MOVA(l);
11793             pic16_emitcode("movx","@%s,a",rname);
11794
11795             if (size)
11796                 pic16_emitcode("inc","%s",rname);
11797
11798             offset++;
11799         }
11800     }
11801     
11802     /* now some housekeeping stuff */
11803     if (aop) {
11804         /* we had to allocate for this iCode */
11805         pic16_freeAsmop(NULL,aop,ic,TRUE);
11806     } else { 
11807         /* we did not allocate which means left
11808            already in a pointer register, then
11809            if size > 0 && this could be used again
11810            we have to point it back to where it 
11811            belongs */
11812         if (AOP_SIZE(right) > 1 &&
11813             !OP_SYMBOL(result)->remat &&
11814             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11815               ic->depth )) {
11816             int size = AOP_SIZE(right) - 1;
11817             while (size--)
11818                 pic16_emitcode("dec","%s",rname);
11819         }
11820     }
11821
11822     /* done */
11823     pic16_freeAsmop(right,NULL,ic,TRUE);
11824     
11825         
11826 }
11827
11828 /*-----------------------------------------------------------------*/
11829 /* genFarPointerSet - set value from far space                     */
11830 /*-----------------------------------------------------------------*/
11831 static void genFarPointerSet (operand *right,
11832                               operand *result, iCode *ic)
11833 {
11834     int size, offset ;
11835     sym_link *retype = getSpec(operandType(right));
11836
11837     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11838     pic16_aopOp(result,ic,FALSE);
11839
11840     /* if the operand is already in dptr 
11841     then we do nothing else we move the value to dptr */
11842     if (AOP_TYPE(result) != AOP_STR) {
11843         /* if this is remateriazable */
11844         if (AOP_TYPE(result) == AOP_IMMD)
11845             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11846         else { /* we need to get it byte by byte */
11847             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11848             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11849             if (options.model == MODEL_FLAT24)
11850             {
11851                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11852             }
11853         }
11854     }
11855     /* so dptr know contains the address */
11856     pic16_freeAsmop(result,NULL,ic,TRUE);
11857     pic16_aopOp(right,ic,FALSE);
11858
11859     /* if bit then unpack */
11860     if (IS_BITFIELD(retype)) 
11861         genPackBits(retype,result,right,"dptr",FPOINTER);
11862     else {
11863         size = AOP_SIZE(right);
11864         offset = 0 ;
11865
11866         while (size--) {
11867             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11868             MOVA(l);
11869             pic16_emitcode("movx","@dptr,a");
11870             if (size)
11871                 pic16_emitcode("inc","dptr");
11872         }
11873     }
11874
11875     pic16_freeAsmop(right,NULL,ic,TRUE);
11876 }
11877
11878 /*-----------------------------------------------------------------*/
11879 /* genGenPointerSet - set value from generic pointer space         */
11880 /*-----------------------------------------------------------------*/
11881 #if 0
11882 static void genGenPointerSet (operand *right,
11883                               operand *result, iCode *ic)
11884 {
11885         int i, size, offset, lit;
11886         sym_link *retype = getSpec(operandType(right));
11887
11888         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11889
11890         pic16_aopOp(result,ic,FALSE);
11891         pic16_aopOp(right,ic,FALSE);
11892         size = AOP_SIZE(right);
11893         offset = 0;
11894
11895         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11896
11897         /* if the operand is already in dptr 
11898                 then we do nothing else we move the value to dptr */
11899         if (AOP_TYPE(result) != AOP_STR) {
11900                 /* if this is remateriazable */
11901                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11902                 // WARNING: anythig until "else" is untested!
11903                 if (AOP_TYPE(result) == AOP_IMMD) {
11904                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11905                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11906                         // load FSR0 from immediate
11907                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11908                         offset = 0;
11909                         while(size--) {
11910                                 if(size) {
11911                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11912                                 } else {
11913                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11914                                 }
11915                                 offset++;
11916                         }
11917                         goto release;
11918                 }
11919                 else { /* we need to get it byte by byte */
11920                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11921                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11922
11923                         // set up FSR0 with address of result
11924                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11925                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11926
11927                         /* hack hack! see if this the FSR. If so don't load W */
11928                         if(AOP_TYPE(right) != AOP_ACC) {
11929
11930                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11931
11932                                 if(AOP_TYPE(right) == AOP_LIT)
11933                                 {
11934                                         // copy literal
11935                                         // note: pic16_popGet handles sign extension
11936                                         for(i=0;i<size;i++) {
11937                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11938                                                 if(i < size-1)
11939                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11940                                                 else
11941                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11942                                         }
11943                                 } else {
11944                                         // copy regs
11945
11946                                         for(i=0;i<size;i++) {
11947                                                 if(i < size-1)
11948                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11949                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11950                                                 else
11951                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11952                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11953                                         }
11954                                 }
11955                                 goto release;
11956                         } 
11957                         // right = ACC
11958                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11959                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11960                         goto release;
11961         } // if (AOP_TYPE(result) != AOP_IMMD)
11962
11963         } // if (AOP_TYPE(result) != AOP_STR)
11964         /* so dptr know contains the address */
11965
11966
11967         /* if bit then unpack */
11968         if (IS_BITFIELD(retype)) 
11969                 genPackBits(retype,result,right,"dptr",GPOINTER);
11970         else {
11971                 size = AOP_SIZE(right);
11972                 offset = 0 ;
11973
11974                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11975
11976                 // set up FSR0 with address of result
11977                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11978                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11979         
11980                 while (size--) {
11981                         if (AOP_TYPE(right) == AOP_LIT) {
11982                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11983                                 if (size) {
11984                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11985                                 } else {
11986                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11987                                 }
11988                         } else { // no literal
11989                                 if(size) {
11990                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11991                                 } else {
11992                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11993                                 }
11994                         }
11995                         offset++;
11996                 }
11997         }
11998
11999         release:
12000         pic16_freeAsmop(right,NULL,ic,TRUE);
12001         pic16_freeAsmop(result,NULL,ic,TRUE);
12002 }
12003 #endif
12004
12005 static void genGenPointerSet (operand *right,
12006                               operand *result, iCode *ic)
12007 {
12008   int size;
12009   sym_link *retype = getSpec(operandType(result));
12010
12011     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12012
12013     pic16_aopOp(result,ic,FALSE);
12014     pic16_aopOp(right,ic,FALSE);
12015     size = AOP_SIZE(right);
12016
12017     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12018
12019
12020     /* if bit then unpack */
12021     if (IS_BITFIELD(retype)) {
12022 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12023       genPackBits(retype,result,right,"dptr",GPOINTER);
12024       goto release;
12025     }
12026
12027     size = AOP_SIZE(right);
12028
12029     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12030
12031
12032     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12033
12034     /* value of right+0 is placed on stack, which will be retrieved
12035      * by the support function this restoring the stack. The important
12036      * thing is that there is no need to manually restore stack pointer
12037      * here */
12038     pushaop(AOP(right), 0);
12039 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12040     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12041     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12042     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12043     
12044     /* load address to write to in WREG:FSR0H:FSR0L */
12045     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12046                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12047     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12048                                 pic16_popCopyReg(&pic16_pc_prodl)));
12049     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12050     
12051     pic16_callGenericPointerRW(1, size);
12052
12053 release:
12054     pic16_freeAsmop(right,NULL,ic,TRUE);
12055     pic16_freeAsmop(result,NULL,ic,TRUE);
12056 }
12057
12058 /*-----------------------------------------------------------------*/
12059 /* genPointerSet - stores the value into a pointer location        */
12060 /*-----------------------------------------------------------------*/
12061 static void genPointerSet (iCode *ic)
12062 {    
12063   operand *right, *result ;
12064   sym_link *type, *etype;
12065   int p_type;
12066
12067     FENTRY;
12068
12069     right = IC_RIGHT(ic);
12070     result = IC_RESULT(ic) ;
12071
12072     /* depending on the type of pointer we need to
12073     move it to the correct pointer register */
12074     type = operandType(result);
12075     etype = getSpec(type);
12076     
12077     /* if left is of type of pointer then it is simple */
12078     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12079         p_type = DCL_TYPE(type);
12080     }
12081     else {
12082         /* we have to go by the storage class */
12083         p_type = PTR_TYPE(SPEC_OCLS(etype));
12084
12085 /*      if (SPEC_OCLS(etype)->codesp ) { */
12086 /*          p_type = CPOINTER ;  */
12087 /*      } */
12088 /*      else */
12089 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12090 /*              p_type = FPOINTER ; */
12091 /*          else */
12092 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12093 /*                  p_type = PPOINTER ; */
12094 /*              else */
12095 /*                  if (SPEC_OCLS(etype) == idata ) */
12096 /*                      p_type = IPOINTER ; */
12097 /*                  else */
12098 /*                      p_type = POINTER ; */
12099     }
12100
12101     /* now that we have the pointer type we assign
12102     the pointer values */
12103     switch (p_type) {
12104       case POINTER:
12105       case IPOINTER:
12106         genNearPointerSet (right,result,ic);
12107         break;
12108
12109       case PPOINTER:
12110         genPagedPointerSet (right,result,ic);
12111         break;
12112
12113       case FPOINTER:
12114         genFarPointerSet (right,result,ic);
12115         break;
12116         
12117       case GPOINTER:
12118         genGenPointerSet (right,result,ic);
12119         break;
12120
12121       default:
12122         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12123           "genPointerSet: illegal pointer type");
12124     }
12125 }
12126
12127 /*-----------------------------------------------------------------*/
12128 /* genIfx - generate code for Ifx statement                        */
12129 /*-----------------------------------------------------------------*/
12130 static void genIfx (iCode *ic, iCode *popIc)
12131 {
12132   operand *cond = IC_COND(ic);
12133   int isbit =0;
12134
12135     FENTRY;
12136
12137     pic16_aopOp(cond,ic,FALSE);
12138
12139     /* get the value into acc */
12140     if (AOP_TYPE(cond) != AOP_CRY)
12141       pic16_toBoolean(cond);
12142     else
12143       isbit = 1;
12144     /* the result is now in the accumulator */
12145     pic16_freeAsmop(cond,NULL,ic,TRUE);
12146
12147     /* if there was something to be popped then do it */
12148     if (popIc)
12149       genIpop(popIc);
12150
12151     /* if the condition is  a bit variable */
12152     if (isbit && IS_ITEMP(cond) && 
12153         SPIL_LOC(cond)) {
12154       genIfxJump(ic,"c");
12155       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12156     } else {
12157       if (isbit && !IS_ITEMP(cond))
12158         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12159         else
12160         genIfxJump(ic,"a");
12161     }
12162     ic->generated = 1;
12163 }
12164
12165 /*-----------------------------------------------------------------*/
12166 /* genAddrOf - generates code for address of                       */
12167 /*-----------------------------------------------------------------*/
12168 static void genAddrOf (iCode *ic)
12169 {
12170   operand *result, *left;
12171   int size;
12172   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12173   pCodeOp *pcop0, *pcop1, *pcop2;
12174
12175     FENTRY;
12176
12177     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12178
12179     sym = OP_SYMBOL( IC_LEFT(ic) );
12180     
12181     if(sym->onStack) {
12182       /* get address of symbol on stack */
12183       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12184 #if 0
12185       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12186                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12187 #endif
12188
12189       // operands on stack are accessible via "FSR2 + index" with index
12190       // starting at 2 for arguments and growing from 0 downwards for
12191       // local variables (index == 0 is not assigned so we add one here)
12192       {
12193         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12194         if (soffs <= 0) {
12195           assert (soffs < 0);
12196           soffs++;
12197         } // if
12198         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12199         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12200         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12201         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12202         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12203         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12204         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12205       }
12206
12207       goto release;
12208     }
12209         
12210 //      if(pic16_debug_verbose) {
12211 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12212 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12213 //      }
12214         
12215     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12216     size = AOP_SIZE(IC_RESULT(ic));
12217
12218     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12219     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12220     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12221         
12222     if (size == 3) {
12223       pic16_emitpcode(POC_MOVLW, pcop0);
12224       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12225       pic16_emitpcode(POC_MOVLW, pcop1);
12226       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12227       pic16_emitpcode(POC_MOVLW, pcop2);
12228       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12229     } else
12230     if (size == 2) {
12231       pic16_emitpcode(POC_MOVLW, pcop0);
12232       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12233       pic16_emitpcode(POC_MOVLW, pcop1);
12234     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12235     } else {
12236       pic16_emitpcode(POC_MOVLW, pcop0);
12237       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12238     }
12239
12240     pic16_freeAsmop(left, NULL, ic, FALSE);
12241 release:
12242     pic16_freeAsmop(result,NULL,ic,TRUE);
12243 }
12244
12245
12246 #if 0
12247 /*-----------------------------------------------------------------*/
12248 /* genFarFarAssign - assignment when both are in far space         */
12249 /*-----------------------------------------------------------------*/
12250 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12251 {
12252     int size = AOP_SIZE(right);
12253     int offset = 0;
12254     char *l ;
12255     /* first push the right side on to the stack */
12256     while (size--) {
12257         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12258         MOVA(l);
12259         pic16_emitcode ("push","acc");
12260     }
12261     
12262     pic16_freeAsmop(right,NULL,ic,FALSE);
12263     /* now assign DPTR to result */
12264     pic16_aopOp(result,ic,FALSE);
12265     size = AOP_SIZE(result);
12266     while (size--) {
12267         pic16_emitcode ("pop","acc");
12268         pic16_aopPut(AOP(result),"a",--offset);
12269     }
12270     pic16_freeAsmop(result,NULL,ic,FALSE);
12271         
12272 }
12273 #endif
12274
12275 /*-----------------------------------------------------------------*/
12276 /* genAssign - generate code for assignment                        */
12277 /*-----------------------------------------------------------------*/
12278 static void genAssign (iCode *ic)
12279 {
12280   operand *result, *right;
12281   int size, offset,know_W;
12282   unsigned long lit = 0L;
12283
12284   result = IC_RESULT(ic);
12285   right  = IC_RIGHT(ic) ;
12286
12287   FENTRY;
12288   
12289   /* if they are the same */
12290   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12291     return ;
12292
12293   /* reversed order operands are aopOp'ed so that result operand
12294    * is effective in case right is a stack symbol. This maneauver
12295    * allows to use the _G.resDirect flag later */
12296   pic16_aopOp(result,ic,TRUE);
12297   pic16_aopOp(right,ic,FALSE);
12298
12299   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12300
12301   /* if they are the same registers */
12302   if (pic16_sameRegs(AOP(right),AOP(result)))
12303     goto release;
12304
12305   /* if the result is a bit */
12306   if (AOP_TYPE(result) == AOP_CRY) {
12307     /* if the right size is a literal then
12308        we know what the value is */
12309     if (AOP_TYPE(right) == AOP_LIT) {
12310           
12311       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12312                   pic16_popGet(AOP(result),0));
12313
12314       if (((int) operandLitValue(right))) 
12315         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12316                        AOP(result)->aopu.aop_dir,
12317                        AOP(result)->aopu.aop_dir);
12318       else
12319         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12320                        AOP(result)->aopu.aop_dir,
12321                        AOP(result)->aopu.aop_dir);
12322       goto release;
12323     }
12324
12325     /* the right is also a bit variable */
12326     if (AOP_TYPE(right) == AOP_CRY) {
12327       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12328       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12329       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12330
12331       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12332                      AOP(result)->aopu.aop_dir,
12333                      AOP(result)->aopu.aop_dir);
12334       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12335                      AOP(right)->aopu.aop_dir,
12336                      AOP(right)->aopu.aop_dir);
12337       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12338                      AOP(result)->aopu.aop_dir,
12339                      AOP(result)->aopu.aop_dir);
12340       goto release ;
12341     }
12342
12343     /* we need to or */
12344     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12345     pic16_toBoolean(right);
12346     emitSKPZ;
12347     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12348     //pic16_aopPut(AOP(result),"a",0);
12349     goto release ;
12350   }
12351
12352   /* bit variables done */
12353   /* general case */
12354   size = AOP_SIZE(result);
12355   offset = 0 ;
12356
12357   if(AOP_TYPE(right) == AOP_LIT) {
12358         if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12359                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12360         else{
12361            union {
12362               unsigned long lit_int;
12363               float lit_float;
12364             } info;
12365         
12366
12367               if(IS_FIXED16X16(operandType(right))) {
12368                 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12369               } else {
12370                 /* take care if literal is a float */
12371                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12372                 lit = info.lit_int;
12373               }
12374         }
12375   }
12376
12377 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12378 //                      sizeof(unsigned long int), sizeof(float));
12379
12380
12381   if (AOP_TYPE(right) == AOP_REG) {
12382     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12383     while (size--) {
12384       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12385     } // while
12386     goto release;
12387   }
12388
12389   /* when do we have to read the program memory?
12390    * - if right itself is a symbol in code space
12391    *   (we don't care what it points to if it's a pointer)
12392    * - AND right is not a function (we would want its address)
12393    */
12394   if(AOP_TYPE(right) != AOP_LIT
12395         && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12396         && !IS_FUNC(OP_SYM_TYPE(right))
12397         && !IS_ITEMP(right))
12398   {
12399         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12400         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12401
12402         // set up table pointer
12403         if(is_LitOp(right)) {
12404 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12405                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12406                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12407                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12408                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12409                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12410                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12411         } else {
12412 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12413                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12414                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12415                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12416                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12417                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12418                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12419         }
12420
12421         /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12422         size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12423         while(size--) {
12424                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12425                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12426                         pic16_popGet(AOP(result),offset)));
12427                 offset++;
12428         }
12429
12430         /* FIXME: for pointers we need to extend differently (according
12431          * to pointer type DATA/CODE/EEPROM/... :*/
12432         size = getSize(OP_SYM_TYPE(right));
12433         if(AOP_SIZE(result) > size) {
12434                 size = AOP_SIZE(result) - size;
12435                 while(size--) {
12436                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12437                         offset++;
12438                 }
12439         }
12440         goto release;
12441   }
12442
12443
12444
12445 #if 0
12446 /* VR - What is this?! */
12447   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12448     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12449     if(aopIdx(AOP(result),0) == 4) {
12450
12451       /* this is a workaround to save value of right into wreg too,
12452        * value of wreg is going to be used later */
12453       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12454       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12455       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12456       goto release;
12457     } else
12458 //      assert(0);
12459       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12460   }
12461 #endif
12462
12463   know_W=-1;
12464   while (size--) {
12465   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12466     if(AOP_TYPE(right) == AOP_LIT) {
12467       if(lit&0xff) {
12468         if(know_W != (lit&0xff))
12469           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12470         know_W = lit&0xff;
12471         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12472       } else
12473         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12474
12475       lit >>= 8;
12476
12477     } else if (AOP_TYPE(right) == AOP_CRY) {
12478       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12479       if(offset == 0) {
12480         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12481         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12482         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12483       }
12484     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12485         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12486         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12487     } else {
12488       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12489
12490       if(!_G.resDirect)         /* use this aopForSym feature */
12491         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12492     }
12493             
12494     offset++;
12495   }
12496   
12497  release:
12498   pic16_freeAsmop (right,NULL,ic,FALSE);
12499   pic16_freeAsmop (result,NULL,ic,TRUE);
12500 }   
12501
12502 /*-----------------------------------------------------------------*/
12503 /* genJumpTab - generates code for jump table                       */
12504 /*-----------------------------------------------------------------*/
12505 static void genJumpTab (iCode *ic)
12506 {
12507   symbol *jtab;
12508   char *l;
12509   pCodeOp *jt_offs;
12510   pCodeOp *jt_offs_hi;
12511   pCodeOp *jt_label;
12512
12513     FENTRY;
12514
12515     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12516     /* get the condition into accumulator */
12517     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12518     MOVA(l);
12519     /* multiply by three */
12520     pic16_emitcode("add","a,acc");
12521     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12522
12523     jtab = newiTempLabel(NULL);
12524     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12525     pic16_emitcode("jmp","@a+dptr");
12526     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12527
12528 #if 0
12529     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12530     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12531     emitSKPNC;
12532     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12533     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12534     pic16_emitpLabel(jtab->key);
12535
12536 #else
12537
12538     jt_offs = pic16_popGetTempReg(0);
12539     jt_offs_hi = pic16_popGetTempReg(1);
12540     jt_label = pic16_popGetLabel (jtab->key);
12541     //fprintf (stderr, "Creating jump table...\n");
12542
12543     // calculate offset into jump table (idx * sizeof (GOTO))
12544     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12545     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12546     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12547     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12548     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12549     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12550     pic16_emitpcode(POC_MOVWF , jt_offs);
12551
12552     // prepare PCLATx (set to first entry in jump table)
12553     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12554     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12555     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12556     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12557     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12558
12559     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12560     pic16_emitpcode(POC_ADDWF , jt_offs);
12561     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12562     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12563     emitSKPNC;
12564     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12565
12566     // release temporaries and prepare jump into table (new PCL --> WREG)
12567     pic16_emitpcode(POC_MOVFW , jt_offs);
12568     pic16_popReleaseTempReg (jt_offs_hi, 1);
12569     pic16_popReleaseTempReg (jt_offs, 0);
12570
12571     // jump into the table
12572     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12573
12574     pic16_emitpLabelFORCE(jtab->key);
12575 #endif
12576
12577     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12578 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12579
12580     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12581     /* now generate the jump labels */
12582     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12583          jtab = setNextItem(IC_JTLABELS(ic))) {
12584 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12585         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12586         
12587     }
12588     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12589
12590 }
12591
12592 /*-----------------------------------------------------------------*/
12593 /* genMixedOperation - gen code for operators between mixed types  */
12594 /*-----------------------------------------------------------------*/
12595 /*
12596   TSD - Written for the PIC port - but this unfortunately is buggy.
12597   This routine is good in that it is able to efficiently promote 
12598   types to different (larger) sizes. Unfortunately, the temporary
12599   variables that are optimized out by this routine are sometimes
12600   used in other places. So until I know how to really parse the 
12601   iCode tree, I'm going to not be using this routine :(.
12602 */
12603 static int genMixedOperation (iCode *ic)
12604 {
12605 #if 0
12606   operand *result = IC_RESULT(ic);
12607   sym_link *ctype = operandType(IC_LEFT(ic));
12608   operand *right = IC_RIGHT(ic);
12609   int ret = 0;
12610   int big,small;
12611   int offset;
12612
12613   iCode *nextic;
12614   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12615
12616   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12617
12618   nextic = ic->next;
12619   if(!nextic)
12620     return 0;
12621
12622   nextright = IC_RIGHT(nextic);
12623   nextleft  = IC_LEFT(nextic);
12624   nextresult = IC_RESULT(nextic);
12625
12626   pic16_aopOp(right,ic,FALSE);
12627   pic16_aopOp(result,ic,FALSE);
12628   pic16_aopOp(nextright,  nextic, FALSE);
12629   pic16_aopOp(nextleft,   nextic, FALSE);
12630   pic16_aopOp(nextresult, nextic, FALSE);
12631
12632   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12633
12634     operand *t = right;
12635     right = nextright;
12636     nextright = t; 
12637
12638     pic16_emitcode(";remove right +","");
12639
12640   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12641 /*
12642     operand *t = right;
12643     right = nextleft;
12644     nextleft = t; 
12645 */
12646     pic16_emitcode(";remove left +","");
12647   } else
12648     return 0;
12649
12650   big = AOP_SIZE(nextleft);
12651   small = AOP_SIZE(nextright);
12652
12653   switch(nextic->op) {
12654
12655   case '+':
12656     pic16_emitcode(";optimize a +","");
12657     /* if unsigned or not an integral type */
12658     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12659       pic16_emitcode(";add a bit to something","");
12660     } else {
12661
12662       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12663
12664       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12665         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12666         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12667       } else
12668         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12669
12670       offset = 0;
12671       while(--big) {
12672
12673         offset++;
12674
12675         if(--small) {
12676           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12677             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12678             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12679           }
12680
12681           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12682           emitSKPNC;
12683           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12684                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12685                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12686           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12687           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12688
12689         } else {
12690           pic16_emitcode("rlf","known_zero,w");
12691
12692           /*
12693             if right is signed
12694               btfsc  right,7
12695                addlw ff
12696           */
12697           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12698             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12699             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12700           } else {
12701             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12702           }
12703         }
12704       }
12705       ret = 1;
12706     }
12707   }
12708   ret = 1;
12709
12710 release:
12711   pic16_freeAsmop(right,NULL,ic,TRUE);
12712   pic16_freeAsmop(result,NULL,ic,TRUE);
12713   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12714   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12715   if(ret)
12716     nextic->generated = 1;
12717
12718   return ret;
12719 #else
12720   return 0;
12721 #endif
12722 }
12723 /*-----------------------------------------------------------------*/
12724 /* genCast - gen code for casting                                  */
12725 /*-----------------------------------------------------------------*/
12726 static void genCast (iCode *ic)
12727 {
12728   operand *result = IC_RESULT(ic);
12729   sym_link *ctype = operandType(IC_LEFT(ic));
12730   sym_link *rtype = operandType(IC_RIGHT(ic));
12731   sym_link *restype = operandType(IC_RESULT(ic));
12732   operand *right = IC_RIGHT(ic);
12733   int size, offset ;
12734
12735
12736     FENTRY;
12737
12738         /* if they are equivalent then do nothing */
12739 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12740 //              return ;
12741
12742         pic16_aopOp(result,ic,FALSE);
12743         pic16_aopOp(right,ic,FALSE) ;
12744
12745         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12746
12747
12748         /* if the result is a bit */
12749         if (AOP_TYPE(result) == AOP_CRY) {
12750         
12751                 /* if the right size is a literal then
12752                  * we know what the value is */
12753                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12754
12755                 if (AOP_TYPE(right) == AOP_LIT) {
12756                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12757                                 pic16_popGet(AOP(result),0));
12758
12759                         if (((int) operandLitValue(right))) 
12760                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12761                                         AOP(result)->aopu.aop_dir,
12762                                         AOP(result)->aopu.aop_dir);
12763                         else
12764                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12765                                         AOP(result)->aopu.aop_dir,
12766                                         AOP(result)->aopu.aop_dir);
12767                         goto release;
12768                 }
12769
12770                 /* the right is also a bit variable */
12771                 if (AOP_TYPE(right) == AOP_CRY) {
12772                         emitCLRC;
12773                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12774
12775                         pic16_emitcode("clrc","");
12776                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12777                                 AOP(right)->aopu.aop_dir,
12778                                 AOP(right)->aopu.aop_dir);
12779                         pic16_aopPut(AOP(result),"c",0);
12780                         goto release ;
12781                 }
12782
12783                 /* we need to or */
12784                 if (AOP_TYPE(right) == AOP_REG) {
12785                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12786                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12787                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12788                 }
12789                 pic16_toBoolean(right);
12790                 pic16_aopPut(AOP(result),"a",0);
12791                 goto release ;
12792         }
12793
12794         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12795           int offset = 1;
12796
12797                 size = AOP_SIZE(result);
12798
12799                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12800
12801                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12802                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12803                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12804
12805                 while (size--)
12806                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12807
12808                 goto release;
12809         }
12810
12811         if(IS_BITFIELD(getSpec(restype))
12812           && IS_BITFIELD(getSpec(rtype))) {
12813           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12814         }
12815
12816         /* if they are the same size : or less */
12817         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12818
12819                 /* if they are in the same place */
12820                 if (pic16_sameRegs(AOP(right),AOP(result)))
12821                         goto release;
12822
12823                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12824 #if 0
12825                 if (IS_PTR_CONST(rtype))
12826 #else
12827                 if (IS_CODEPTR(rtype))
12828 #endif
12829                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12830
12831 #if 0
12832                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12833 #else
12834                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12835 #endif
12836                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12837
12838 #if 0
12839                 if(AOP_TYPE(right) == AOP_IMMD) {
12840                   pCodeOp *pcop0, *pcop1, *pcop2;
12841                   symbol *sym = OP_SYMBOL( right );
12842
12843                         size = AOP_SIZE(result);
12844                         /* low */
12845                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12846                         /* high */
12847                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12848                         /* upper */
12849                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12850         
12851                         if (size == 3) {
12852                                 pic16_emitpcode(POC_MOVLW, pcop0);
12853                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12854                                 pic16_emitpcode(POC_MOVLW, pcop1);
12855                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12856                                 pic16_emitpcode(POC_MOVLW, pcop2);
12857                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12858                         } else
12859                         if (size == 2) {
12860                                 pic16_emitpcode(POC_MOVLW, pcop0);
12861                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12862                                 pic16_emitpcode(POC_MOVLW, pcop1);
12863                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12864                         } else {
12865                                 pic16_emitpcode(POC_MOVLW, pcop0);
12866                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12867                         }
12868                 } else
12869 #endif
12870                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12871                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12872                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12873                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12874                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12875                         if(AOP_SIZE(result) <2)
12876                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12877                 } else {
12878                         /* if they in different places then copy */
12879                         size = AOP_SIZE(result);
12880                         offset = 0 ;
12881                         while (size--) {
12882                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12883                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12884                                 offset++;
12885                         }
12886                 }
12887                 goto release;
12888         }
12889
12890         /* if the result is of type pointer */
12891         if (IS_PTR(ctype)) {
12892           int p_type;
12893           sym_link *type = operandType(right);
12894           sym_link *etype = getSpec(type);
12895
12896                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
12897
12898                 /* pointer to generic pointer */
12899                 if (IS_GENPTR(ctype)) {
12900                   char *l = zero;
12901             
12902                         if (IS_PTR(type)) 
12903                                 p_type = DCL_TYPE(type);
12904                         else {
12905                 /* we have to go by the storage class */
12906                 p_type = PTR_TYPE(SPEC_OCLS(etype));
12907
12908 /*              if (SPEC_OCLS(etype)->codesp )  */
12909 /*                  p_type = CPOINTER ;  */
12910 /*              else */
12911 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12912 /*                      p_type = FPOINTER ; */
12913 /*                  else */
12914 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12915 /*                          p_type = PPOINTER; */
12916 /*                      else */
12917 /*                          if (SPEC_OCLS(etype) == idata ) */
12918 /*                              p_type = IPOINTER ; */
12919 /*                          else */
12920 /*                              p_type = POINTER ; */
12921             }
12922                 
12923             /* the first two bytes are known */
12924       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
12925             size = GPTRSIZE - 1; 
12926             offset = 0 ;
12927             while (size--) {
12928               if(offset < AOP_SIZE(right)) {
12929                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12930                 pic16_mov2f(AOP(result), AOP(right), offset);
12931 /*
12932                 if ((AOP_TYPE(right) == AOP_PCODE) && 
12933                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12934                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12935                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12936                 } else { 
12937                   
12938                   pic16_aopPut(AOP(result),
12939                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12940                          offset);
12941                 }
12942 */
12943               } else 
12944                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12945               offset++;
12946             }
12947             /* the last byte depending on type */
12948             switch (p_type) {
12949             case IPOINTER:
12950             case POINTER:
12951                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12952                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12953 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
12954                 break;
12955
12956             case CPOINTER:
12957                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12958                 break;
12959
12960             case FPOINTER:
12961               pic16_emitcode(";BUG!? ","%d",__LINE__);
12962                 l = one;
12963                 break;
12964             case PPOINTER:
12965               pic16_emitcode(";BUG!? ","%d",__LINE__);
12966                 l = "#0x03";
12967                 break;
12968
12969             case GPOINTER:
12970                 if (GPTRSIZE > AOP_SIZE(right)) {
12971                   // assume data pointer... THIS MIGHT BE WRONG!
12972                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12973                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12974                 } else {
12975                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12976                 }
12977               break;
12978               
12979             default:
12980                 /* this should never happen */
12981                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
12982                        "got unknown pointer type");
12983                 exit(1);
12984             }
12985             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
12986             goto release ;
12987         }
12988         
12989         
12990         assert( 0 );
12991         /* just copy the pointers */
12992         size = AOP_SIZE(result);
12993         offset = 0 ;
12994         while (size--) {
12995             pic16_aopPut(AOP(result),
12996                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12997                    offset);
12998             offset++;
12999         }
13000         goto release ;
13001     }
13002     
13003
13004
13005     /* so we now know that the size of destination is greater
13006     than the size of the source.
13007     Now, if the next iCode is an operator then we might be
13008     able to optimize the operation without performing a cast.
13009     */
13010     if(genMixedOperation(ic))
13011       goto release;
13012
13013     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13014     
13015     /* we move to result for the size of source */
13016     size = AOP_SIZE(right);
13017     offset = 0 ;
13018
13019     while (size--) {
13020       if(!_G.resDirect)
13021         pic16_mov2f(AOP(result), AOP(right), offset);
13022       offset++;
13023     }
13024
13025     /* now depending on the sign of the destination */
13026     size = AOP_SIZE(result) - AOP_SIZE(right);
13027     /* if unsigned or not an integral type */
13028     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13029       while (size--)
13030         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13031     } else {
13032       /* we need to extend the sign :( */
13033
13034       if(size == 1) {
13035         /* Save one instruction of casting char to int */
13036         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13037         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13038         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13039       } else {
13040         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13041
13042         if(offset)
13043           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13044         else
13045           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13046         
13047         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13048
13049         while (size--)
13050           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13051       }
13052     }
13053
13054 release:
13055     pic16_freeAsmop(right,NULL,ic,TRUE);
13056     pic16_freeAsmop(result,NULL,ic,TRUE);
13057
13058 }
13059
13060 /*-----------------------------------------------------------------*/
13061 /* genDjnz - generate decrement & jump if not zero instrucion      */
13062 /*-----------------------------------------------------------------*/
13063 static int genDjnz (iCode *ic, iCode *ifx)
13064 {
13065     symbol *lbl, *lbl1;
13066     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13067
13068     if (!ifx)
13069         return 0;
13070     
13071     /* if the if condition has a false label
13072        then we cannot save */
13073     if (IC_FALSE(ifx))
13074         return 0;
13075
13076     /* if the minus is not of the form 
13077        a = a - 1 */
13078     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13079         !IS_OP_LITERAL(IC_RIGHT(ic)))
13080         return 0;
13081
13082     if (operandLitValue(IC_RIGHT(ic)) != 1)
13083         return 0;
13084
13085     /* if the size of this greater than one then no
13086        saving */
13087     if (getSize(operandType(IC_RESULT(ic))) > 1)
13088         return 0;
13089
13090     /* otherwise we can save BIG */
13091     lbl = newiTempLabel(NULL);
13092     lbl1= newiTempLabel(NULL);
13093
13094     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13095     
13096     if (IS_AOP_PREG(IC_RESULT(ic))) {
13097         pic16_emitcode("dec","%s",
13098                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13099         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13100         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13101     } else {    
13102
13103
13104       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13105       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13106
13107       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13108       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13109
13110     }
13111     
13112     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13113     ifx->generated = 1;
13114     return 1;
13115 }
13116
13117 /*-----------------------------------------------------------------*/
13118 /* genReceive - generate code for a receive iCode                  */
13119 /*-----------------------------------------------------------------*/
13120 static void genReceive (iCode *ic)
13121 {    
13122
13123   FENTRY;
13124
13125 #if 0
13126   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13127         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13128 #endif
13129 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13130
13131   if (isOperandInFarSpace(IC_RESULT(ic))
13132       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13133           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13134
13135     int size = getSize(operandType(IC_RESULT(ic)));
13136     int offset =  pic16_fReturnSizePic - size;
13137
13138       assert( 0 );
13139       while (size--) {
13140         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13141                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13142                       offset++;
13143         }
13144
13145       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13146
13147       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13148       size = AOP_SIZE(IC_RESULT(ic));
13149       offset = 0;
13150       while (size--) {
13151         pic16_emitcode ("pop","acc");
13152         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13153       }
13154   } else {
13155     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13156     _G.accInUse++;
13157     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13158     _G.accInUse--;
13159
13160     /* set pseudo stack pointer to where it should be - dw*/
13161     GpsuedoStkPtr = ic->parmBytes;
13162
13163     /* setting GpsuedoStkPtr has side effects here: */
13164     assignResultValue(IC_RESULT(ic), 0);
13165   }
13166
13167   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13168 }
13169
13170 /*-----------------------------------------------------------------*/
13171 /* genDummyRead - generate code for dummy read of volatiles        */
13172 /*-----------------------------------------------------------------*/
13173 static void
13174 genDummyRead (iCode * ic)
13175 {
13176   operand *op;
13177   int i;
13178
13179   op = IC_RIGHT(ic);
13180   if (op && IS_SYMOP(op)) {
13181     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13182       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13183       return;
13184     }
13185     pic16_aopOp (op, ic, FALSE);
13186     for (i=0; i < AOP_SIZE(op); i++) {
13187       // may need to protect this from the peepholer -- this is not nice but works...
13188       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13189       pic16_mov2w (AOP(op),i);
13190       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13191     } // for i
13192     pic16_freeAsmop (op, NULL, ic, TRUE);
13193   } else if (op) {
13194     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13195   } // if
13196 }
13197
13198 /*-----------------------------------------------------------------*/
13199 /* genpic16Code - generate code for pic16 based controllers        */
13200 /*-----------------------------------------------------------------*/
13201 /*
13202  * At this point, ralloc.c has gone through the iCode and attempted
13203  * to optimize in a way suitable for a PIC. Now we've got to generate
13204  * PIC instructions that correspond to the iCode.
13205  *
13206  * Once the instructions are generated, we'll pass through both the
13207  * peep hole optimizer and the pCode optimizer.
13208  *-----------------------------------------------------------------*/
13209
13210 void genpic16Code (iCode *lic)
13211 {
13212   iCode *ic;
13213   int cln = 0;
13214
13215     lineHead = lineCurr = NULL;
13216
13217     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13218     pic16_addpBlock(pb);
13219
13220 #if 0
13221     /* if debug information required */
13222     if (options.debug && currFunc) {
13223       if (currFunc) {
13224         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13225       }
13226     }
13227 #endif
13228
13229     for (ic = lic ; ic ; ic = ic->next ) {
13230
13231       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13232       if ( cln != ic->lineno ) {
13233         if ( options.debug ) {
13234           debugFile->writeCLine (ic);
13235         }
13236         
13237         if(!options.noCcodeInAsm) {
13238           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13239               printCLine(ic->filename, ic->lineno)));
13240         }
13241
13242         cln = ic->lineno ;
13243       }
13244         
13245       if(options.iCodeInAsm) {
13246         char *l;
13247
13248           /* insert here code to print iCode as comment */
13249           l = Safe_strdup(printILine(ic));
13250           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13251       }
13252         
13253       /* if the result is marked as
13254        * spilt and rematerializable or code for
13255        * this has already been generated then
13256        * do nothing */
13257       if (resultRemat(ic) || ic->generated ) 
13258         continue ;
13259         
13260       /* depending on the operation */
13261       switch (ic->op) {
13262         case '!' :
13263           pic16_genNot(ic);
13264           break;
13265             
13266         case '~' :
13267           pic16_genCpl(ic);
13268           break;
13269             
13270         case UNARYMINUS:
13271           genUminus (ic);
13272           break;
13273             
13274         case IPUSH:
13275           genIpush (ic);
13276           break;
13277             
13278         case IPOP:
13279           /* IPOP happens only when trying to restore a 
13280            * spilt live range, if there is an ifx statement
13281            * following this pop then the if statement might
13282            * be using some of the registers being popped which
13283            * would destroy the contents of the register so
13284            * we need to check for this condition and handle it */
13285            if (ic->next
13286              && ic->next->op == IFX
13287              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13288                genIfx (ic->next,ic);
13289           else
13290             genIpop (ic);
13291           break; 
13292             
13293         case CALL:
13294           genCall (ic);
13295           break;
13296             
13297         case PCALL:
13298           genPcall (ic);
13299           break;
13300             
13301         case FUNCTION:
13302           genFunction (ic);
13303           break;
13304             
13305         case ENDFUNCTION:
13306           genEndFunction (ic);
13307           break;
13308             
13309         case RETURN:
13310           genRet (ic);
13311           break;
13312             
13313         case LABEL:
13314           genLabel (ic);
13315           break;
13316             
13317         case GOTO:
13318           genGoto (ic);
13319           break;
13320             
13321         case '+' :
13322           pic16_genPlus (ic) ;
13323           break;
13324             
13325         case '-' :
13326           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13327             pic16_genMinus (ic);
13328           break;
13329
13330         case '*' :
13331           genMult (ic);
13332           break;
13333             
13334         case '/' :
13335           genDiv (ic) ;
13336           break;
13337             
13338         case '%' :
13339           genMod (ic);
13340           break;
13341             
13342         case '>' :
13343           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13344           break;
13345             
13346         case '<' :
13347           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13348           break;
13349             
13350         case LE_OP:
13351         case GE_OP:
13352         case NE_OP:
13353           /* note these two are xlated by algebraic equivalence
13354            * during parsing SDCC.y */
13355           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13356             "got '>=' or '<=' shouldn't have come here");
13357           break;
13358
13359         case EQ_OP:
13360           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13361           break;            
13362             
13363         case AND_OP:
13364           genAndOp (ic);
13365           break;
13366             
13367         case OR_OP:
13368           genOrOp (ic);
13369           break;
13370             
13371         case '^' :
13372           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13373           break;
13374             
13375         case '|' :
13376           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13377           break;
13378             
13379         case BITWISEAND:
13380           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13381           break;
13382             
13383         case INLINEASM:
13384           genInline (ic);
13385           break;
13386             
13387         case RRC:
13388           genRRC (ic);
13389           break;
13390             
13391         case RLC:
13392           genRLC (ic);
13393           break;
13394             
13395         case GETHBIT:
13396           genGetHbit (ic);
13397           break;
13398             
13399         case LEFT_OP:
13400           genLeftShift (ic);
13401           break;
13402             
13403         case RIGHT_OP:
13404           genRightShift (ic);
13405           break;
13406             
13407         case GET_VALUE_AT_ADDRESS:
13408           genPointerGet(ic);
13409           break;
13410             
13411         case '=' :
13412           if (POINTER_SET(ic))
13413             genPointerSet(ic);
13414           else
13415             genAssign(ic);
13416           break;
13417             
13418         case IFX:
13419           genIfx (ic,NULL);
13420           break;
13421             
13422         case ADDRESS_OF:
13423           genAddrOf (ic);
13424           break;
13425             
13426         case JUMPTABLE:
13427           genJumpTab (ic);
13428           break;
13429             
13430         case CAST:
13431           genCast (ic);
13432           break;
13433             
13434         case RECEIVE:
13435           genReceive(ic);
13436           break;
13437             
13438         case SEND:
13439           addSet(&_G.sendSet,ic);
13440           break;
13441
13442         case DUMMY_READ_VOLATILE:
13443           genDummyRead (ic);
13444           break;
13445
13446         default :
13447           ic = ic;
13448       }
13449     }
13450
13451
13452     /* now we are ready to call the
13453        peep hole optimizer */
13454     if (!options.nopeep)
13455       peepHole (&lineHead);
13456
13457     /* now do the actual printing */
13458     printLine (lineHead, codeOutFile);
13459
13460 #ifdef PCODE_DEBUG
13461     DFPRINTF((stderr,"printing pBlock\n\n"));
13462     pic16_printpBlock(stdout,pb);
13463 #endif
13464
13465     return;
13466 }
13467