570188af1303f578b0dbfa6be7505939c870f9d2
[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     /* if float then do float stuff */
2834     if (IS_FLOAT(optype)) {
2835       genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2836       goto release;
2837     }
2838
2839     /* otherwise subtract from zero by taking the 2's complement */
2840     size = AOP_SIZE(IC_LEFT(ic));
2841     label = newiTempLabel ( NULL );
2842     
2843     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2844       for (i=size-1; i > 0; i--) {
2845         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2846       } // for
2847       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2848       for (i=1; i < size; i++) {
2849         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2850         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2851       } // for
2852     } else {
2853       for (i=size-1; i >= 0; i--) {
2854         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2855         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2856       } // for
2857       if (size > 1) {
2858         for (i=0; i < size-2; i++) {
2859           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2860           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2861         } // for
2862         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2863       } // if
2864       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2865     }
2866     if (needLabel)
2867       pic16_emitpLabel (label->key);
2868
2869 release:
2870     /* release the aops */
2871     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2872     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2873 }
2874
2875 #if 0
2876 /*-----------------------------------------------------------------*/
2877 /* saveRegisters - will look for a call and save the registers     */
2878 /*-----------------------------------------------------------------*/
2879 static void saveRegisters(iCode *lic) 
2880 {
2881     int i;
2882     iCode *ic;
2883     bitVect *rsave;
2884     sym_link *dtype;
2885
2886     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2887     /* look for call */
2888     for (ic = lic ; ic ; ic = ic->next) 
2889         if (ic->op == CALL || ic->op == PCALL)
2890             break;
2891
2892     if (!ic) {
2893         fprintf(stderr,"found parameter push with no function call\n");
2894         return ;
2895     }
2896
2897     /* if the registers have been saved already then
2898     do nothing */
2899     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2900         return ;
2901
2902     /* find the registers in use at this time 
2903     and push them away to safety */
2904     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2905                           ic->rUsed);
2906
2907     ic->regsSaved = 1;
2908     if (options.useXstack) {
2909         if (bitVectBitValue(rsave,R0_IDX))
2910             pic16_emitcode("mov","b,r0");
2911         pic16_emitcode("mov","r0,%s",spname);
2912         for (i = 0 ; i < pic16_nRegs ; i++) {
2913             if (bitVectBitValue(rsave,i)) {
2914                 if (i == R0_IDX)
2915                     pic16_emitcode("mov","a,b");
2916                 else
2917                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2918                 pic16_emitcode("movx","@r0,a");
2919                 pic16_emitcode("inc","r0");
2920             }
2921         }
2922         pic16_emitcode("mov","%s,r0",spname);
2923         if (bitVectBitValue(rsave,R0_IDX))
2924             pic16_emitcode("mov","r0,b");           
2925     }// else
2926     //for (i = 0 ; i < pic16_nRegs ; i++) {
2927     //    if (bitVectBitValue(rsave,i))
2928     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2929     //}
2930
2931     dtype = operandType(IC_LEFT(ic));
2932     if (currFunc && dtype && 
2933         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2934         IFFUNC_ISISR(currFunc->type) &&
2935         !ic->bankSaved) 
2936
2937         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2938
2939 }
2940 /*-----------------------------------------------------------------*/
2941 /* unsaveRegisters - pop the pushed registers                      */
2942 /*-----------------------------------------------------------------*/
2943 static void unsaveRegisters (iCode *ic)
2944 {
2945     int i;
2946     bitVect *rsave;
2947
2948     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2949     /* find the registers in use at this time 
2950     and push them away to safety */
2951     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2952                           ic->rUsed);
2953     
2954     if (options.useXstack) {
2955         pic16_emitcode("mov","r0,%s",spname);   
2956         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2957             if (bitVectBitValue(rsave,i)) {
2958                 pic16_emitcode("dec","r0");
2959                 pic16_emitcode("movx","a,@r0");
2960                 if (i == R0_IDX)
2961                     pic16_emitcode("mov","b,a");
2962                 else
2963                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2964             }       
2965
2966         }
2967         pic16_emitcode("mov","%s,r0",spname);
2968         if (bitVectBitValue(rsave,R0_IDX))
2969             pic16_emitcode("mov","r0,b");
2970     } //else
2971     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2972     //    if (bitVectBitValue(rsave,i))
2973     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2974     //}
2975
2976 }  
2977 #endif
2978
2979 #if 0  // patch 14
2980 /*-----------------------------------------------------------------*/
2981 /* pushSide -                                                      */
2982 /*-----------------------------------------------------------------*/
2983 static void pushSide(operand * oper, int size)
2984 {
2985         int offset = 0;
2986     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2987         while (size--) {
2988                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2989                 if (AOP_TYPE(oper) != AOP_REG &&
2990                     AOP_TYPE(oper) != AOP_DIR &&
2991                     strcmp(l,"a") ) {
2992                         pic16_emitcode("mov","a,%s",l);
2993                         pic16_emitcode("push","acc");
2994                 } else
2995                         pic16_emitcode("push","%s",l);
2996         }
2997 }
2998 #endif // patch 14
2999
3000 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
3001 {
3002   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3003     pic16_emitpcode(POC_MOVFW, src);
3004     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
3005   } else {
3006     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3007         src, pic16_popGet(AOP(op), offset)));
3008   }
3009 }
3010
3011
3012 /*-----------------------------------------------------------------*/
3013 /* assignResultValue - assign results to oper, rescall==1 is       */
3014 /*                     called from genCall() or genPcall()         */
3015 /*-----------------------------------------------------------------*/
3016 static void assignResultValue(operand * oper, int rescall)
3017 {
3018   int size = AOP_SIZE(oper);
3019   int offset=0;
3020   
3021     FENTRY2;
3022 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3023     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3024
3025     if(rescall) {
3026       /* assign result from a call/pcall function() */
3027                 
3028       /* function results are stored in a special order,
3029        * see top of file with Function return policy, or manual */
3030
3031       if(size <= 4) {
3032         /* 8-bits, result in WREG */
3033         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3034                         
3035         if(size>1) {
3036           /* 16-bits, result in PRODL:WREG */
3037           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3038         }
3039                         
3040         if(size>2) {
3041           /* 24-bits, result in PRODH:PRODL:WREG */
3042           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3043         }
3044                         
3045         if(size>3) {
3046           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3047           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3048         }
3049       
3050       } else {
3051         /* >32-bits, result on stack, and FSR0 points to beginning.
3052          * Fix stack when done */
3053         /* FIXME FIXME */
3054 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3055         while (size--) {
3056 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3057 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3058                 
3059           popaopidx(AOP(oper), size, GpsuedoStkPtr);
3060           GpsuedoStkPtr++;
3061         }
3062                         
3063         /* fix stack */
3064         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3065         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3066         if(STACK_MODEL_LARGE) {
3067           emitSKPNC;
3068           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3069         }
3070       }                 
3071     } else {
3072       int areg = 0;             /* matching argument register */
3073       
3074 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3075       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3076
3077
3078       /* its called from genReceive (probably) -- VR */
3079       /* I hope this code will not be called from somewhere else in the future! 
3080        * We manually set the pseudo stack pointer in genReceive. - dw
3081        */
3082       if(!GpsuedoStkPtr && _G.useWreg) {
3083 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3084
3085         /* The last byte in the assignment is in W */
3086         if(areg <= GpsuedoStkPtr) {
3087           size--;
3088           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3089           offset++;
3090 //          debugf("receive from WREG\n", 0);
3091         }
3092         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3093       }
3094 //      GpsuedoStkPtr++;
3095       _G.stack_lat = AOP_SIZE(oper)-1;
3096
3097       while (size) {
3098         size--;
3099         GpsuedoStkPtr++;
3100         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3101 //        debugf("receive from STACK\n", 0);
3102         offset++;
3103       }
3104     }
3105 }
3106
3107
3108 /*-----------------------------------------------------------------*/
3109 /* genIpush - generate code for pushing this gets a little complex */
3110 /*-----------------------------------------------------------------*/
3111 static void genIpush (iCode *ic)
3112 {
3113 //  int size, offset=0;
3114
3115   FENTRY;
3116   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3117
3118   if(ic->parmPush) {
3119     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3120
3121     /* send to stack as normal */
3122     addSet(&_G.sendSet,ic);
3123 //    addSetHead(&_G.sendSet,ic);
3124     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3125   }
3126
3127         
3128 #if 0
3129     int size, offset = 0 ;
3130     char *l;
3131
3132
3133     /* if this is not a parm push : ie. it is spill push 
3134     and spill push is always done on the local stack */
3135     if (!ic->parmPush) {
3136
3137         /* and the item is spilt then do nothing */
3138         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3139             return ;
3140
3141         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3142         size = AOP_SIZE(IC_LEFT(ic));
3143         /* push it on the stack */
3144         while(size--) {
3145             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3146             if (*l == '#') {
3147                 MOVA(l);
3148                 l = "acc";
3149             }
3150             pic16_emitcode("push","%s",l);
3151         }
3152         return ;        
3153     }
3154
3155     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3156 #endif
3157 }
3158
3159 /*-----------------------------------------------------------------*/
3160 /* genIpop - recover the registers: can happen only for spilling   */
3161 /*-----------------------------------------------------------------*/
3162 static void genIpop (iCode *ic)
3163 {
3164   FENTRY;
3165   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3166 #if 0
3167     int size,offset ;
3168
3169
3170     /* if the temp was not pushed then */
3171     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3172         return ;
3173
3174     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3175     size = AOP_SIZE(IC_LEFT(ic));
3176     offset = (size-1);
3177     while (size--) 
3178         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3179                                    FALSE,TRUE));
3180
3181     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3182 #endif
3183 }
3184
3185 #if 0
3186 /*-----------------------------------------------------------------*/
3187 /* unsaverbank - restores the resgister bank from stack            */
3188 /*-----------------------------------------------------------------*/
3189 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3190 {
3191   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3192 #if 0
3193     int i;
3194     asmop *aop ;
3195     regs *r = NULL;
3196
3197     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3198     if (popPsw) {
3199         if (options.useXstack) {
3200             aop = newAsmop(0);
3201             r = getFreePtr(ic,&aop,FALSE);
3202             
3203             
3204             pic16_emitcode("mov","%s,_spx",r->name);
3205             pic16_emitcode("movx","a,@%s",r->name);
3206             pic16_emitcode("mov","psw,a");
3207             pic16_emitcode("dec","%s",r->name);
3208             
3209         }else
3210             pic16_emitcode ("pop","psw");
3211     }
3212
3213     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3214         if (options.useXstack) {       
3215             pic16_emitcode("movx","a,@%s",r->name);
3216             //pic16_emitcode("mov","(%s+%d),a",
3217             //       regspic16[i].base,8*bank+regspic16[i].offset);
3218             pic16_emitcode("dec","%s",r->name);
3219
3220         } else 
3221           pic16_emitcode("pop",""); //"(%s+%d)",
3222         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3223     }
3224
3225     if (options.useXstack) {
3226
3227         pic16_emitcode("mov","_spx,%s",r->name);
3228         pic16_freeAsmop(NULL,aop,ic,TRUE);
3229
3230     }
3231 #endif 
3232 }
3233
3234 /*-----------------------------------------------------------------*/
3235 /* saverbank - saves an entire register bank on the stack          */
3236 /*-----------------------------------------------------------------*/
3237 static void saverbank (int bank, iCode *ic, bool pushPsw)
3238 {
3239   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3240 #if 0
3241     int i;
3242     asmop *aop ;
3243     regs *r = NULL;
3244
3245     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3246     if (options.useXstack) {
3247
3248         aop = newAsmop(0);
3249         r = getFreePtr(ic,&aop,FALSE);  
3250         pic16_emitcode("mov","%s,_spx",r->name);
3251
3252     }
3253
3254     for (i = 0 ; i < pic16_nRegs ;i++) {
3255         if (options.useXstack) {
3256             pic16_emitcode("inc","%s",r->name);
3257             //pic16_emitcode("mov","a,(%s+%d)",
3258             //         regspic16[i].base,8*bank+regspic16[i].offset);
3259             pic16_emitcode("movx","@%s,a",r->name);           
3260         } else 
3261           pic16_emitcode("push","");// "(%s+%d)",
3262                      //regspic16[i].base,8*bank+regspic16[i].offset);
3263     }
3264     
3265     if (pushPsw) {
3266         if (options.useXstack) {
3267             pic16_emitcode("mov","a,psw");
3268             pic16_emitcode("movx","@%s,a",r->name);     
3269             pic16_emitcode("inc","%s",r->name);
3270             pic16_emitcode("mov","_spx,%s",r->name);       
3271             pic16_freeAsmop (NULL,aop,ic,TRUE);
3272             
3273         } else
3274             pic16_emitcode("push","psw");
3275         
3276         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3277     }
3278     ic->bankSaved = 1;
3279 #endif
3280 }
3281 #endif  /* 0 */
3282
3283
3284 static int wparamCmp(void *p1, void *p2)
3285 {
3286   return (!strcmp((char *)p1, (char *)p2));
3287 }
3288
3289 int inWparamList(char *s)
3290 {
3291   return isinSetWith(wparamList, s, wparamCmp);
3292
3293
3294
3295 /*-----------------------------------------------------------------*/
3296 /* genCall - generates a call statement                            */
3297 /*-----------------------------------------------------------------*/
3298 static void genCall (iCode *ic)
3299 {
3300   sym_link *ftype;   
3301   int stackParms=0;
3302   int use_wreg=0;
3303   int inwparam=0;
3304   char *fname;
3305   
3306     FENTRY;
3307
3308     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3309     /* if caller saves & we have not saved then */
3310 //    if (!ic->regsSaved)
3311 //      saveRegisters(ic);
3312
3313         /* initialise stackParms for IPUSH pushes */
3314 //      stackParms = psuedoStkPtr;
3315 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3316     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3317     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3318
3319 #if 0
3320     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3321 #endif
3322
3323     /* if send set is not empty the assign */
3324     if (_G.sendSet) {
3325       iCode *sic;
3326       int psuedoStkPtr=-1; 
3327       int firstTimeThruLoop = 1;
3328
3329
3330         /* reverse sendSet if function is not reentrant */
3331         if(!IFFUNC_ISREENT(ftype))
3332           _G.sendSet = reverseSet(_G.sendSet);
3333
3334         /* First figure how many parameters are getting passed */
3335         stackParms = 0;
3336         use_wreg = 0;
3337         
3338         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3339           int size;
3340 //          int offset = 0;
3341
3342             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3343             size = AOP_SIZE(IC_LEFT(sic));
3344
3345             stackParms += size;
3346
3347             /* pass the last byte through WREG */
3348             if(inwparam) {
3349
3350               while (size--) {
3351                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3352                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3353                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3354
3355                 if(!firstTimeThruLoop) {
3356                   /* If this is not the first time we've been through the loop
3357                    * then we need to save the parameter in a temporary
3358                    * register. The last byte of the last parameter is
3359                    * passed in W. */
3360
3361                   pushw();
3362 //                  --psuedoStkPtr;             // sanity check
3363                   use_wreg = 1;
3364                 }
3365                 
3366                 firstTimeThruLoop=0;
3367
3368                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3369
3370 //                offset++;
3371               }
3372             } else {
3373               /* all arguments are passed via stack */
3374               use_wreg = 0;
3375
3376               while (size--) {
3377                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3378                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3379                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3380
3381 //                pushaop(AOP(IC_LEFT(sic)), size);
3382                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3383
3384                 if(!_G.resDirect)
3385                   pushw();
3386               }
3387             }
3388
3389             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3390           }
3391
3392           if(inwparam) {
3393             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3394               pushw();  /* save last parameter to stack if functions has varargs */
3395               use_wreg = 0;
3396             } else
3397               use_wreg = 1;
3398           } else use_wreg = 0;
3399
3400           _G.stackRegSet = _G.sendSet;
3401           _G.sendSet = NULL;
3402     }
3403
3404     /* make the call */
3405     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3406
3407     GpsuedoStkPtr=0;
3408     
3409     /* if we need to assign a result value */
3410     if ((IS_ITEMP(IC_RESULT(ic))
3411           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3412               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3413         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3414
3415       _G.accInUse++;
3416       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3417       _G.accInUse--;
3418
3419       assignResultValue(IC_RESULT(ic), 1);
3420
3421       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3422                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3423                 
3424       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3425     }
3426
3427     if(!stackParms && ic->parmBytes) {
3428       stackParms = ic->parmBytes;
3429     }
3430       
3431     stackParms -= use_wreg;
3432     
3433     if(stackParms>0) {
3434       if(stackParms == 1) {
3435         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3436       } else {
3437         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3438         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3439       }
3440       if(STACK_MODEL_LARGE) {
3441         emitSKPNC;
3442         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3443       }
3444     }
3445
3446 #if 0
3447     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3448 #endif
3449
3450     /* adjust the stack for parameters if required */
3451 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3452
3453 #if 0
3454       /* if register bank was saved then pop them */
3455       if (ic->bankSaved)
3456         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3457
3458       /* if we hade saved some registers then unsave them */
3459       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3460         unsaveRegisters (ic);
3461 #endif
3462 }
3463
3464
3465
3466 /*-----------------------------------------------------------------*/
3467 /* genPcall - generates a call by pointer statement                */
3468 /*            new version, created from genCall - HJD              */
3469 /*-----------------------------------------------------------------*/
3470 static void genPcall (iCode *ic)
3471 {
3472   sym_link *ftype, *fntype;
3473   int stackParms=0;
3474   symbol *retlbl = newiTempLabel(NULL);
3475   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3476   
3477     FENTRY;
3478
3479     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3480     fntype = operandType( IC_LEFT(ic) )->next;
3481
3482     /* if send set is not empty the assign */
3483     if (_G.sendSet) {
3484       iCode *sic;
3485       int psuedoStkPtr=-1; 
3486
3487       /* reverse sendSet if function is not reentrant */
3488       if(!IFFUNC_ISREENT(fntype))
3489         _G.sendSet = reverseSet(_G.sendSet);
3490
3491       stackParms = 0;
3492       
3493       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3494         int size;
3495
3496           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3497           size = AOP_SIZE(IC_LEFT(sic));
3498           stackParms += size;
3499
3500           /* all parameters are passed via stack, since WREG is clobbered
3501            * by the calling sequence */
3502           while (size--) {
3503             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3504             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3505             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3506
3507             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3508             pushw();
3509           }
3510
3511           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3512       }
3513
3514       _G.stackRegSet = _G.sendSet;
3515       _G.sendSet = NULL;
3516     }
3517
3518     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3519
3520     // push return address
3521     // push $ on return stack, then replace with retlbl
3522
3523     /* Thanks to Thorsten Klose for pointing out that the following
3524      * snippet should be interrupt safe */
3525     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3526     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3527
3528     pic16_emitpcodeNULLop(POC_PUSH);
3529
3530     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3531     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3532     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3533     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3534     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3535     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3536
3537
3538     /* restore interrupt control register */
3539     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3540     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3541
3542     /* make the call by writing the pointer into pc */
3543     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3544     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3545
3546     // note: MOVFF to PCL not allowed
3547     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3548     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3549
3550
3551     /* return address is here: (X) */
3552     pic16_emitpLabelFORCE(retlbl->key);
3553
3554     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3555
3556     GpsuedoStkPtr=0;
3557     /* if we need assign a result value */
3558     if ((IS_ITEMP(IC_RESULT(ic))
3559           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3560               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3561         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3562
3563       _G.accInUse++;
3564       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3565       _G.accInUse--;
3566
3567       assignResultValue(IC_RESULT(ic), 1);
3568
3569       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3570               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3571                 
3572       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3573     }
3574
3575 //    stackParms -= use_wreg;
3576     
3577     if(stackParms>0) {
3578       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3579       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3580       if(STACK_MODEL_LARGE) {
3581         emitSKPNC;
3582         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3583       }
3584     }
3585 }
3586
3587 /*-----------------------------------------------------------------*/
3588 /* resultRemat - result  is rematerializable                       */
3589 /*-----------------------------------------------------------------*/
3590 static int resultRemat (iCode *ic)
3591 {
3592   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3593   if (SKIP_IC(ic) || ic->op == IFX)
3594     return 0;
3595
3596   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3597     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3598     if (sym->remat && !POINTER_SET(ic)) 
3599       return 1;
3600   }
3601
3602   return 0;
3603 }
3604
3605 #if defined(__BORLANDC__) || defined(_MSC_VER)
3606 #define STRCASECMP stricmp
3607 #else
3608 #define STRCASECMP strcasecmp
3609 #endif
3610
3611 #if 0
3612 /*-----------------------------------------------------------------*/
3613 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3614 /*-----------------------------------------------------------------*/
3615 static bool inExcludeList(char *s)
3616 {
3617   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3618     int i =0;
3619     
3620     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3621     if (options.excludeRegs[i] &&
3622     STRCASECMP(options.excludeRegs[i],"none") == 0)
3623         return FALSE ;
3624
3625     for ( i = 0 ; options.excludeRegs[i]; i++) {
3626         if (options.excludeRegs[i] &&
3627         STRCASECMP(s,options.excludeRegs[i]) == 0)
3628             return TRUE;
3629     }
3630     return FALSE ;
3631 }
3632 #endif
3633
3634 /*-----------------------------------------------------------------*/
3635 /* genFunction - generated code for function entry                 */
3636 /*-----------------------------------------------------------------*/
3637 static void genFunction (iCode *ic)
3638 {
3639   symbol *sym;
3640   sym_link *ftype;
3641   
3642     FENTRY;
3643     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3644
3645     pic16_labelOffset += (max_key+4);
3646     max_key=0;
3647     GpsuedoStkPtr=0;
3648     _G.nRegsSaved = 0;
3649         
3650     ftype = operandType(IC_LEFT(ic));
3651     sym = OP_SYMBOL(IC_LEFT(ic));
3652
3653     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3654       /* create an absolute section at the interrupt vector:
3655        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3656       symbol *asym;
3657       char asymname[128];
3658       pBlock *apb;
3659
3660 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3661
3662         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3663           sprintf(asymname, "ivec_%s", sym->name);
3664         else
3665           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3666   
3667         /* when an interrupt is declared as naked, do not emit the special
3668          * wrapper segment at vector address. The user should take care for
3669          * this instead. -- VR */
3670
3671         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3672           asym = newSymbol(asymname, 0);
3673           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3674           pic16_addpBlock( apb );
3675
3676           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3677           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3678           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3679           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3680           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3681                 
3682           /* mark the end of this tiny function */
3683           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3684         } else {
3685           sprintf(asymname, "%s", sym->rname);
3686         }
3687
3688         {
3689           absSym *abSym;
3690
3691             abSym = Safe_calloc(1, sizeof(absSym));
3692             strcpy(abSym->name, asymname);
3693
3694             switch( FUNC_INTNO(sym->type) ) {
3695               case 0: abSym->address = 0x000000; break;
3696               case 1: abSym->address = 0x000008; break;
3697               case 2: abSym->address = 0x000018; break;
3698               
3699               default:
3700 //                fprintf(stderr, "no interrupt number is given\n");
3701                 abSym->address = -1; break;
3702             }
3703
3704             /* relocate interrupt vectors if needed */
3705             if(abSym->address != -1)
3706               abSym->address += pic16_options.ivt_loc;
3707
3708             addSet(&absSymSet, abSym);
3709         }
3710     }
3711
3712     /* create the function header */
3713     pic16_emitcode(";","-----------------------------------------");
3714     pic16_emitcode(";"," function %s",sym->name);
3715     pic16_emitcode(";","-----------------------------------------");
3716
3717     pic16_emitcode("","%s:",sym->rname);
3718     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3719
3720     {
3721       absSym *ab;
3722
3723         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3724           if(!strcmp(ab->name, sym->rname)) {
3725             pic16_pBlockConvert2Absolute(pb);
3726             break;
3727           }
3728         }
3729     }
3730
3731     if(IFFUNC_ISNAKED(ftype)) {
3732       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3733       return;
3734     }
3735         
3736     /* if critical function then turn interrupts off */
3737     if (IFFUNC_ISCRITICAL(ftype)) {
3738       //pic16_emitcode("clr","ea");
3739     }
3740
3741     currFunc = sym;             /* update the currFunc symbol */
3742     _G.fregsUsed = sym->regsUsed;
3743     _G.sregsAlloc = newBitVect(128);
3744     
3745
3746     /* if this is an interrupt service routine then
3747      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3748     if (IFFUNC_ISISR(sym->type)) {
3749         _G.usefastretfie = 1;   /* use shadow registers by default */
3750         
3751         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3752         if(!FUNC_ISSHADOWREGS(sym->type)) {
3753           /* do not save WREG,STATUS,BSR for high priority interrupts
3754            * because they are stored in the hardware shadow registers already */
3755           _G.usefastretfie = 0;
3756           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3757           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3758           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3759         }
3760
3761         /* these should really be optimized somehow, because not all
3762          * interrupt handlers modify them */
3763         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3764         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3765         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3766         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3767         
3768 //        pic16_pBlockConvert2ISR(pb);
3769     }
3770
3771     /* emit code to setup stack frame if user enabled,
3772      * and function is not main() */
3773     
3774 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3775     if(strcmp(sym->name, "main")) {
3776       if(0 
3777         || !options.ommitFramePtr 
3778 //        || sym->regsUsed
3779         || IFFUNC_ARGS(sym->type)
3780         || FUNC_HASSTACKPARM(sym->etype)
3781         ) {
3782         /* setup the stack frame */
3783         if(STACK_MODEL_LARGE)
3784           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3785         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3786
3787         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3788         if(STACK_MODEL_LARGE)
3789           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3790       }
3791     }
3792
3793     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3794           && sym->stack) {
3795
3796       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3797
3798       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3799       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3800       emitSKPC;
3801       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3802     }
3803           
3804     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3805       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3806         _G.useWreg = 0;
3807       else
3808         _G.useWreg = 1;
3809     } else
3810       _G.useWreg = 0;
3811
3812     /* if callee-save to be used for this function
3813      * then save the registers being used in this function */
3814 //    if (IFFUNC_CALLEESAVES(sym->type))
3815     {
3816       int i;
3817
3818         /* if any registers used */
3819         if (sym->regsUsed) {
3820           /* save the registers used */
3821           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3822           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3823           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3824             if (bitVectBitValue(sym->regsUsed,i)) {
3825               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3826               _G.nRegsSaved++;
3827
3828               if(!pic16_regWithIdx(i)->wasUsed) {
3829                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3830                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3831                 pic16_regWithIdx(i)->wasUsed = 1;
3832               }
3833             }
3834           }
3835           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3836         }
3837     }
3838         
3839     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3840 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3841 }
3842
3843 /*-----------------------------------------------------------------*/
3844 /* genEndFunction - generates epilogue for functions               */
3845 /*-----------------------------------------------------------------*/
3846 static void genEndFunction (iCode *ic)
3847 {
3848   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3849
3850     FENTRY;
3851
3852     if(IFFUNC_ISNAKED(sym->type)) {
3853       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3854       return;
3855     }
3856
3857     _G.stack_lat = 0;
3858
3859     /* add code for ISCRITICAL */
3860     if(IFFUNC_ISCRITICAL(sym->type)) {
3861       /* if critical function, turn on interrupts */
3862       
3863       /* TODO: add code here -- VR */
3864     }
3865     
3866 //    sym->regsUsed = _G.fregsUsed;
3867     
3868     /* now we need to restore the registers */
3869     /* if any registers used */
3870
3871     /* first restore registers that might be used for stack access */
3872     if(_G.sregsAllocSet) {
3873     regs *sr;
3874     
3875       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3876       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3877         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3878       }
3879     }
3880
3881     if (sym->regsUsed) {
3882       int i;
3883
3884         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3885         /* restore registers used */
3886         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3887         for ( i = sym->regsUsed->size; i >= 0; i--) {
3888           if (bitVectBitValue(sym->regsUsed,i)) {
3889             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3890             _G.nRegsSaved--;
3891           }
3892         }
3893         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3894     }
3895
3896       
3897
3898     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3899           && sym->stack) {
3900       if (sym->stack == 1) {
3901         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3902         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3903       } else {
3904         // we have to add more than one...
3905         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3906         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3907         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3908         emitSKPNC;
3909         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3910         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3911         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3912       }
3913     }
3914
3915     if(strcmp(sym->name, "main")) {
3916       if(0
3917         || !options.ommitFramePtr
3918 //        || sym->regsUsed
3919         || IFFUNC_ARGS(sym->type)
3920         || FUNC_HASSTACKPARM(sym->etype)
3921         ) {
3922         /* restore stack frame */
3923         if(STACK_MODEL_LARGE)
3924           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3925         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3926       }
3927     }
3928
3929     _G.useWreg = 0;
3930
3931     if (IFFUNC_ISISR(sym->type)) {
3932       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3933       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3934       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3935       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3936
3937       if(!FUNC_ISSHADOWREGS(sym->type)) {
3938         /* do not restore interrupt vector for WREG,STATUS,BSR
3939          * for high priority interrupt, see genFunction */
3940         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3941         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3942         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3943       }
3944 //      _G.interruptvector = 0;         /* sanity check */
3945
3946
3947       /* if debug then send end of function */
3948 /*      if (options.debug && currFunc)  */
3949       if (currFunc) {
3950         debugFile->writeEndFunction (currFunc, ic, 1);
3951       }
3952         
3953       if(_G.usefastretfie)
3954         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3955       else
3956         pic16_emitpcodeNULLop(POC_RETFIE);
3957
3958       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3959       
3960       _G.usefastretfie = 0;
3961       return;
3962     }
3963
3964     if (IFFUNC_ISCRITICAL(sym->type)) {
3965       pic16_emitcode("setb","ea");
3966     }
3967
3968     /* if debug then send end of function */
3969     if (currFunc) {
3970       debugFile->writeEndFunction (currFunc, ic, 1);
3971     }
3972
3973     /* insert code to restore stack frame, if user enabled it
3974      * and function is not main() */
3975          
3976
3977     pic16_emitpcodeNULLop(POC_RETURN);
3978
3979     /* Mark the end of a function */
3980     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3981 }
3982
3983
3984 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3985 {
3986   unsigned long lit=1;
3987   operand *op;
3988
3989     op = IC_LEFT(ic);
3990   
3991     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3992     if(AOP_TYPE(op) == AOP_LIT) {
3993       if(!IS_FLOAT(operandType( op ))) {
3994         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3995       } else {
3996         union {
3997           unsigned long lit_int;
3998           float lit_float;
3999         } info;
4000         
4001         /* take care if literal is a float */
4002         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4003         lit = info.lit_int;
4004       }
4005     }
4006
4007     if(is_LitOp(op)) {
4008       if(/*(OP_LIVETO(op) <= ic->seq) &&*/ (lit == 0)) {
4009         pic16_emitpcode(POC_CLRF, dest);
4010       } else {
4011         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
4012         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
4013       }
4014     } else {
4015       if(dest->type == PO_WREG && (offset == 0)) {
4016         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4017       return;
4018     }
4019     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4020   }
4021 }
4022
4023 /*-----------------------------------------------------------------*/
4024 /* genRet - generate code for return statement                     */
4025 /*-----------------------------------------------------------------*/
4026 static void genRet (iCode *ic)
4027 {
4028   int size;
4029   operand *left;
4030
4031     FENTRY;
4032         /* if we have no return value then
4033          * just generate the "ret" */
4034         
4035         if (!IC_LEFT(ic)) 
4036                 goto jumpret;       
4037     
4038         /* we have something to return then
4039          * move the return value into place */
4040         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4041         size = AOP_SIZE(IC_LEFT(ic));
4042
4043         if(size <= 4) {
4044           if(size>3)
4045             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4046           
4047           if(size>2)
4048             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4049
4050           if(size>1)
4051             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4052           
4053           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4054
4055         } else {
4056                 /* >32-bits, setup stack and FSR0 */
4057                 while (size--) {
4058 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4059 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4060
4061                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4062
4063 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
4064                         GpsuedoStkPtr++;
4065                 }
4066                         
4067                 /* setup FSR0 */
4068                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4069                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4070
4071                 if(STACK_MODEL_LARGE) {
4072                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4073                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4074                 } else {
4075                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4076                 }
4077         }
4078                                 
4079 #if 0
4080         /* old code, left here for reference -- VR */    
4081         while (size--) {
4082           char *l ;
4083
4084                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4085                         /* #NOCHANGE */
4086                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4087                         pic16_emitpcomment("push %s",l);
4088                         pushed++;
4089                 } else {
4090                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4091                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4092                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4093                         
4094                         if (strcmp(fReturn[offset],l)) {
4095                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4096                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4097                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4098                                 } else {
4099                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4100                                 }
4101                                 
4102                                 if(size) {
4103                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4104                                 }
4105                                 offset++;
4106                         }
4107                 }
4108         }    
4109
4110         if (pushed) {
4111                 while(pushed) {
4112                         pushed--;
4113                         if (strcmp(fReturn[pushed],"a"))
4114                                 pic16_emitcode("pop",fReturn[pushed]);
4115                         else
4116                                 pic16_emitcode("pop","acc");
4117                 }
4118         }
4119 #endif
4120
4121
4122         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4123     
4124 jumpret:
4125         /* generate a jump to the return label
4126          * if the next is not the return statement */
4127         if (!(ic->next && ic->next->op == LABEL
4128                 && IC_LABEL(ic->next) == returnLabel)) {
4129         
4130                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4131                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4132         }
4133 }
4134
4135 /*-----------------------------------------------------------------*/
4136 /* genLabel - generates a label                                    */
4137 /*-----------------------------------------------------------------*/
4138 static void genLabel (iCode *ic)
4139 {
4140   FENTRY;
4141
4142   /* special case never generate */
4143   if (IC_LABEL(ic) == entryLabel)
4144     return ;
4145
4146   pic16_emitpLabel(IC_LABEL(ic)->key);
4147 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4148 }
4149
4150 /*-----------------------------------------------------------------*/
4151 /* genGoto - generates a goto                                      */
4152 /*-----------------------------------------------------------------*/
4153 //tsd
4154 static void genGoto (iCode *ic)
4155 {
4156   FENTRY;
4157   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4158 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4159 }
4160
4161
4162 /*-----------------------------------------------------------------*/
4163 /* genMultbits :- multiplication of bits                           */
4164 /*-----------------------------------------------------------------*/
4165 static void genMultbits (operand *left, 
4166                          operand *right, 
4167                          operand *result)
4168 {
4169   FENTRY;
4170
4171   if(!pic16_sameRegs(AOP(result),AOP(right)))
4172     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4173
4174   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4175   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4176   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4177
4178 }
4179
4180
4181 /*-----------------------------------------------------------------*/
4182 /* genMultOneByte : 8 bit multiplication & division                */
4183 /*-----------------------------------------------------------------*/
4184 static void genMultOneByte (operand *left,
4185                             operand *right,
4186                             operand *result)
4187 {
4188
4189   FENTRY;
4190   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4191   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4192
4193   /* (if two literals, the value is computed before) */
4194   /* if one literal, literal on the right */
4195   if (AOP_TYPE(left) == AOP_LIT){
4196     operand *t = right;
4197     right = left;
4198     left = t;
4199   }
4200
4201         /* size is already checked in genMult == 1 */
4202 //      size = AOP_SIZE(result);
4203
4204         if (AOP_TYPE(right) == AOP_LIT){
4205                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4206                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4207                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4208                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4209         } else {
4210                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4211                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4212                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4213                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4214         }
4215         
4216         pic16_genMult8X8_8 (left, right,result);
4217 }
4218
4219 /*-----------------------------------------------------------------*/
4220 /* genMultOneWord : 16 bit multiplication                          */
4221 /*-----------------------------------------------------------------*/
4222 static void genMultOneWord (operand *left,
4223                             operand *right,
4224                             operand *result)
4225 {
4226   FENTRY;
4227   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4228   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4229
4230   /* (if two literals, the value is computed before)
4231    * if one literal, literal on the right */
4232   if (AOP_TYPE(left) == AOP_LIT){
4233     operand *t = right;
4234     right = left;
4235     left = t;
4236   }
4237
4238   /* size is checked already == 2 */
4239 //  size = AOP_SIZE(result);
4240
4241   if (AOP_TYPE(right) == AOP_LIT) {
4242     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4243       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4244       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4245       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4246   } else {
4247     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4248       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4249       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4250       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4251   }
4252         
4253   pic16_genMult16X16_16(left, right,result);
4254 }
4255
4256 /*-----------------------------------------------------------------*/
4257 /* genMultOneLong : 32 bit multiplication                          */
4258 /*-----------------------------------------------------------------*/
4259 static void genMultOneLong (operand *left,
4260                             operand *right,
4261                             operand *result)
4262 {
4263   FENTRY;
4264   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4265   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4266
4267   /* (if two literals, the value is computed before)
4268    * if one literal, literal on the right */
4269   if (AOP_TYPE(left) == AOP_LIT){
4270     operand *t = right;
4271     right = left;
4272     left = t;
4273   }
4274
4275   /* size is checked already == 4 */
4276 //  size = AOP_SIZE(result);
4277
4278   if (AOP_TYPE(right) == AOP_LIT) {
4279     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4280         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4281         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4282         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4283   } else {
4284     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4285         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4286         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4287         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4288   }
4289         
4290   pic16_genMult32X32_32(left, right,result);
4291 }
4292
4293
4294
4295 /*-----------------------------------------------------------------*/
4296 /* genMult - generates code for multiplication                     */
4297 /*-----------------------------------------------------------------*/
4298 static void genMult (iCode *ic)
4299 {
4300   operand *left = IC_LEFT(ic);
4301   operand *right = IC_RIGHT(ic);
4302   operand *result= IC_RESULT(ic);   
4303
4304     FENTRY;
4305         /* assign the amsops */
4306         pic16_aopOp (left,ic,FALSE);
4307         pic16_aopOp (right,ic,FALSE);
4308         pic16_aopOp (result,ic,TRUE);
4309
4310         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4311
4312         /* special cases first *
4313         * both are bits */
4314         if (AOP_TYPE(left) == AOP_CRY
4315                 && AOP_TYPE(right)== AOP_CRY) {
4316                 genMultbits(left,right,result);
4317           goto release ;
4318         }
4319
4320         /* if both are of size == 1 */
4321         if(AOP_SIZE(left) == 1
4322                 && AOP_SIZE(right) == 1) {
4323                 genMultOneByte(left,right,result);
4324           goto release ;
4325         }
4326
4327         /* if both are of size == 2 */
4328         if(AOP_SIZE(left) == 2
4329                 && AOP_SIZE(right) == 2) {
4330                 genMultOneWord(left, right, result);
4331           goto release;
4332         }
4333         
4334         /* if both are of size == 4 */
4335         if(AOP_SIZE(left) == 4
4336                 && AOP_SIZE(right) == 4) {
4337                 genMultOneLong(left, right, result);
4338           goto release;
4339         }
4340         
4341         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4342
4343
4344         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4345         /* should have been converted to function call */
4346         assert(0) ;
4347
4348 release :
4349         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4350         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4351         pic16_freeAsmop(result,NULL,ic,TRUE); 
4352 }
4353
4354 /*-----------------------------------------------------------------*/
4355 /* genDivbits :- division of bits                                  */
4356 /*-----------------------------------------------------------------*/
4357 static void genDivbits (operand *left, 
4358                         operand *right, 
4359                         operand *result)
4360 {
4361   char *l;
4362
4363     FENTRY;
4364     /* the result must be bit */    
4365     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4366     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4367
4368     MOVA(l);    
4369
4370     pic16_emitcode("div","ab");
4371     pic16_emitcode("rrc","a");
4372     pic16_aopPut(AOP(result),"c",0);
4373 }
4374
4375 /*-----------------------------------------------------------------*/
4376 /* genDivOneByte : 8 bit division                                  */
4377 /*-----------------------------------------------------------------*/
4378 static void genDivOneByte (operand *left,
4379                            operand *right,
4380                            operand *result)
4381 {
4382   sym_link *opetype = operandType(result);
4383   char *l ;
4384   symbol *lbl ;
4385   int size,offset;
4386
4387         /* result = divident / divisor
4388          * - divident may be a register or a literal,
4389          * - divisor may be a register or a literal,
4390          * so there are 3 cases (literal / literal is optimized
4391          * by the front-end) to handle.
4392          * In addition we must handle signed and unsigned, which
4393          * result in 6 final different cases -- VR */
4394
4395     FENTRY;
4396     
4397     size = AOP_SIZE(result) - 1;
4398     offset = 1;
4399     /* signed or unsigned */
4400     if (SPEC_USIGN(opetype)) {
4401       pCodeOp *pct1,    /* count */
4402                 *pct2,  /* reste */
4403                 *pct3;  /* temp */
4404       symbol *label1, *label2, *label3;;
4405
4406
4407         /* unsigned is easy */
4408
4409         pct1 = pic16_popGetTempReg(1);
4410         pct2 = pic16_popGetTempReg(1);
4411         pct3 = pic16_popGetTempReg(1);
4412         
4413         label1 = newiTempLabel(NULL);
4414         label2 = newiTempLabel(NULL);
4415         label3 = newiTempLabel(NULL);
4416
4417         /* the following algorithm is extracted from divuint.c */
4418
4419         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4420         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4421         
4422         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4423
4424         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4425         
4426         pic16_emitpLabel(label1->key);
4427         
4428         emitCLRC;
4429         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4430
4431
4432         emitCLRC;
4433         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4434         
4435
4436         emitSKPNC;
4437         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4438         
4439         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4440         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4441         
4442         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4443         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4444         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4445         
4446         pic16_emitpLabel( label3->key );
4447         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4448         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4449         
4450         
4451
4452         pic16_emitpLabel(label2->key);
4453         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4454         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4455         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4456         
4457         /* result is in wreg */
4458         if(AOP_TYPE(result) != AOP_ACC)
4459                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4460
4461         pic16_popReleaseTempReg( pct3, 1);
4462         pic16_popReleaseTempReg( pct2, 1);
4463         pic16_popReleaseTempReg( pct1, 1);
4464
4465         return ;
4466     }
4467
4468     /* signed is a little bit more difficult */
4469
4470     /* save the signs of the operands */
4471     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4472     MOVA(l);    
4473     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4474     pic16_emitcode("push","acc"); /* save it on the stack */
4475
4476     /* now sign adjust for both left & right */
4477     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4478     MOVA(l);       
4479     lbl = newiTempLabel(NULL);
4480     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4481     pic16_emitcode("cpl","a");   
4482     pic16_emitcode("inc","a");
4483     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4484     pic16_emitcode("mov","b,a");
4485
4486     /* sign adjust left side */
4487     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4488     MOVA(l);
4489
4490     lbl = newiTempLabel(NULL);
4491     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4492     pic16_emitcode("cpl","a");
4493     pic16_emitcode("inc","a");
4494     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4495
4496     /* now the division */
4497     pic16_emitcode("div","ab");
4498     /* we are interested in the lower order
4499     only */
4500     pic16_emitcode("mov","b,a");
4501     lbl = newiTempLabel(NULL);
4502     pic16_emitcode("pop","acc");   
4503     /* if there was an over flow we don't 
4504     adjust the sign of the result */
4505     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4506     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4507     CLRC;
4508     pic16_emitcode("clr","a");
4509     pic16_emitcode("subb","a,b");
4510     pic16_emitcode("mov","b,a");
4511     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4512
4513     /* now we are done */
4514     pic16_aopPut(AOP(result),"b",0);
4515     if(size > 0){
4516         pic16_emitcode("mov","c,b.7");
4517         pic16_emitcode("subb","a,acc");   
4518     }
4519     while (size--)
4520         pic16_aopPut(AOP(result),"a",offset++);
4521
4522 }
4523
4524 /*-----------------------------------------------------------------*/
4525 /* genDiv - generates code for division                            */
4526 /*-----------------------------------------------------------------*/
4527 static void genDiv (iCode *ic)
4528 {
4529     operand *left = IC_LEFT(ic);
4530     operand *right = IC_RIGHT(ic);
4531     operand *result= IC_RESULT(ic);   
4532
4533
4534         /* Division is a very lengthy algorithm, so it is better
4535          * to call support routines than inlining algorithm.
4536          * Division functions written here just in case someone
4537          * wants to inline and not use the support libraries -- VR */
4538
4539     FENTRY;
4540     
4541     /* assign the amsops */
4542     pic16_aopOp (left,ic,FALSE);
4543     pic16_aopOp (right,ic,FALSE);
4544     pic16_aopOp (result,ic,TRUE);
4545
4546     /* special cases first */
4547     /* both are bits */
4548     if (AOP_TYPE(left) == AOP_CRY &&
4549         AOP_TYPE(right)== AOP_CRY) {
4550         genDivbits(left,right,result);
4551         goto release ;
4552     }
4553
4554     /* if both are of size == 1 */
4555     if (AOP_SIZE(left) == 1 &&
4556         AOP_SIZE(right) == 1 ) {
4557         genDivOneByte(left,right,result);
4558         goto release ;
4559     }
4560
4561     /* should have been converted to function call */
4562     assert(0);
4563 release :
4564     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4565     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4566     pic16_freeAsmop(result,NULL,ic,TRUE); 
4567 }
4568
4569 /*-----------------------------------------------------------------*/
4570 /* genModbits :- modulus of bits                                   */
4571 /*-----------------------------------------------------------------*/
4572 static void genModbits (operand *left, 
4573                         operand *right, 
4574                         operand *result)
4575 {
4576   char *l;
4577
4578     FENTRY;  
4579     
4580     werror(W_POSSBUG2, __FILE__, __LINE__);
4581     /* the result must be bit */    
4582     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4583     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4584
4585     MOVA(l);       
4586
4587     pic16_emitcode("div","ab");
4588     pic16_emitcode("mov","a,b");
4589     pic16_emitcode("rrc","a");
4590     pic16_aopPut(AOP(result),"c",0);
4591 }
4592
4593 /*-----------------------------------------------------------------*/
4594 /* genModOneByte : 8 bit modulus                                   */
4595 /*-----------------------------------------------------------------*/
4596 static void genModOneByte (operand *left,
4597                            operand *right,
4598                            operand *result)
4599 {
4600   sym_link *opetype = operandType(result);
4601   char *l ;
4602   symbol *lbl ;
4603
4604     FENTRY;
4605     werror(W_POSSBUG2, __FILE__, __LINE__);
4606
4607     /* signed or unsigned */
4608     if (SPEC_USIGN(opetype)) {
4609         /* unsigned is easy */
4610         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4611         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4612         MOVA(l);    
4613         pic16_emitcode("div","ab");
4614         pic16_aopPut(AOP(result),"b",0);
4615         return ;
4616     }
4617
4618     /* signed is a little bit more difficult */
4619
4620     /* save the signs of the operands */
4621     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4622     MOVA(l);
4623
4624     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4625     pic16_emitcode("push","acc"); /* save it on the stack */
4626
4627     /* now sign adjust for both left & right */
4628     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4629     MOVA(l);
4630
4631     lbl = newiTempLabel(NULL);
4632     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4633     pic16_emitcode("cpl","a");   
4634     pic16_emitcode("inc","a");
4635     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4636     pic16_emitcode("mov","b,a"); 
4637
4638     /* sign adjust left side */
4639     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4640     MOVA(l);
4641
4642     lbl = newiTempLabel(NULL);
4643     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4644     pic16_emitcode("cpl","a");   
4645     pic16_emitcode("inc","a");
4646     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4647
4648     /* now the multiplication */
4649     pic16_emitcode("div","ab");
4650     /* we are interested in the lower order
4651     only */
4652     lbl = newiTempLabel(NULL);
4653     pic16_emitcode("pop","acc");   
4654     /* if there was an over flow we don't 
4655     adjust the sign of the result */
4656     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4657     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4658     CLRC ;
4659     pic16_emitcode("clr","a");
4660     pic16_emitcode("subb","a,b");
4661     pic16_emitcode("mov","b,a");
4662     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4663
4664     /* now we are done */
4665     pic16_aopPut(AOP(result),"b",0);
4666
4667 }
4668
4669 /*-----------------------------------------------------------------*/
4670 /* genMod - generates code for division                            */
4671 /*-----------------------------------------------------------------*/
4672 static void genMod (iCode *ic)
4673 {
4674   operand *left = IC_LEFT(ic);
4675   operand *right = IC_RIGHT(ic);
4676   operand *result= IC_RESULT(ic);  
4677
4678     FENTRY;
4679     
4680     /* assign the amsops */
4681     pic16_aopOp (left,ic,FALSE);
4682     pic16_aopOp (right,ic,FALSE);
4683     pic16_aopOp (result,ic,TRUE);
4684
4685     /* special cases first */
4686     /* both are bits */
4687     if (AOP_TYPE(left) == AOP_CRY &&
4688         AOP_TYPE(right)== AOP_CRY) {
4689         genModbits(left,right,result);
4690         goto release ;
4691     }
4692
4693     /* if both are of size == 1 */
4694     if (AOP_SIZE(left) == 1 &&
4695         AOP_SIZE(right) == 1 ) {
4696         genModOneByte(left,right,result);
4697         goto release ;
4698     }
4699
4700     /* should have been converted to function call */
4701     assert(0);
4702
4703 release :
4704     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4705     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4706     pic16_freeAsmop(result,NULL,ic,TRUE); 
4707 }
4708
4709 /*-----------------------------------------------------------------*/
4710 /* genIfxJump :- will create a jump depending on the ifx           */
4711 /*-----------------------------------------------------------------*/
4712 /*
4713   note: May need to add parameter to indicate when a variable is in bit space.
4714 */
4715 static void genIfxJump (iCode *ic, char *jval)
4716 {
4717   FENTRY;
4718   
4719     /* if true label then we jump if condition
4720     supplied is true */
4721     if ( IC_TRUE(ic) ) {
4722
4723         if(strcmp(jval,"a") == 0)
4724           emitSKPZ;
4725         else if (strcmp(jval,"c") == 0)
4726           emitSKPNC;
4727         else {
4728           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4729           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4730         }
4731
4732         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4733         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4734
4735     }
4736     else {
4737         /* false label is present */
4738         if(strcmp(jval,"a") == 0)
4739           emitSKPNZ;
4740         else if (strcmp(jval,"c") == 0)
4741           emitSKPC;
4742         else {
4743           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4744           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4745         }
4746
4747         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4748         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4749
4750     }
4751
4752
4753     /* mark the icode as generated */
4754     ic->generated = 1;
4755 }
4756
4757 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4758 {
4759   FENTRY;
4760   
4761     /* if true label then we jump if condition
4762     supplied is true */
4763     if ( IC_TRUE(ic) ) {
4764       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4765       pic16_emitpcode(POC_BTFSC, jop);
4766
4767       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4768       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4769
4770     } else {
4771       /* false label is present */
4772       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4773       pic16_emitpcode(POC_BTFSS, jop);
4774           
4775       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4776       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4777     }
4778
4779
4780     /* mark the icode as generated */
4781     ic->generated = 1;
4782 }
4783
4784 #if 0
4785 // not needed ATM
4786
4787 /*-----------------------------------------------------------------*/
4788 /* genSkip                                                         */
4789 /*-----------------------------------------------------------------*/
4790 static void genSkip(iCode *ifx,int status_bit)
4791 {
4792   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4793   if(!ifx)
4794     return;
4795
4796   if ( IC_TRUE(ifx) ) {
4797     switch(status_bit) {
4798     case 'z':
4799       emitSKPNZ;
4800       break;
4801
4802     case 'c':
4803       emitSKPNC;
4804       break;
4805
4806     case 'd':
4807       emitSKPDC;
4808       break;
4809
4810     }
4811
4812     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4813     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4814
4815   } else {
4816
4817     switch(status_bit) {
4818
4819     case 'z':
4820       emitSKPZ;
4821       break;
4822
4823     case 'c':
4824       emitSKPC;
4825       break;
4826
4827     case 'd':
4828       emitSKPDC;
4829       break;
4830     }
4831     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4832     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4833
4834   }
4835
4836 }
4837 #endif
4838
4839 /*-----------------------------------------------------------------*/
4840 /* genSkipc                                                        */
4841 /*-----------------------------------------------------------------*/
4842 static void genSkipc(resolvedIfx *rifx)
4843 {
4844   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4845   
4846   if(!rifx)
4847     return;
4848
4849   if(rifx->condition)
4850     emitSKPNC;
4851   else
4852     emitSKPC;
4853
4854   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4855   rifx->generated = 1;
4856 }
4857
4858 #if !(USE_SIMPLE_GENCMP)
4859 /*-----------------------------------------------------------------*/
4860 /* genSkipz2                                                       */
4861 /*-----------------------------------------------------------------*/
4862 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4863 {
4864   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4865   
4866   if(!rifx)
4867     return;
4868
4869   if( (rifx->condition ^ invert_condition) & 1)
4870     emitSKPZ;
4871   else
4872     emitSKPNZ;
4873
4874   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4875   rifx->generated = 1;
4876 }
4877 #endif
4878
4879 #if 0
4880 /*-----------------------------------------------------------------*/
4881 /* genSkipz                                                        */
4882 /*-----------------------------------------------------------------*/
4883 static void genSkipz(iCode *ifx, int condition)
4884 {
4885   if(!ifx)
4886     return;
4887
4888   if(condition)
4889     emitSKPNZ;
4890   else
4891     emitSKPZ;
4892
4893   if ( IC_TRUE(ifx) )
4894     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4895   else
4896     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4897
4898   if ( IC_TRUE(ifx) )
4899     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4900   else
4901     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4902
4903 }
4904 #endif
4905
4906 #if !(USE_SIMPLE_GENCMP)
4907 /*-----------------------------------------------------------------*/
4908 /* genSkipCond                                                     */
4909 /*-----------------------------------------------------------------*/
4910 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4911 {
4912   if(!rifx)
4913     return;
4914
4915   if(rifx->condition)
4916     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4917   else
4918     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4919
4920
4921   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4922   rifx->generated = 1;
4923 }
4924 #endif
4925
4926 #if 0
4927 /*-----------------------------------------------------------------*/
4928 /* genChkZeroes :- greater or less than comparison                 */
4929 /*     For each byte in a literal that is zero, inclusive or the   */
4930 /*     the corresponding byte in the operand with W                */
4931 /*     returns true if any of the bytes are zero                   */
4932 /*-----------------------------------------------------------------*/
4933 static int genChkZeroes(operand *op, int lit,  int size)
4934 {
4935
4936   int i;
4937   int flag =1;
4938
4939   while(size--) {
4940     i = (lit >> (size*8)) & 0xff;
4941
4942     if(i==0) {
4943       if(flag) 
4944         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4945       else
4946         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4947       flag = 0;
4948     }
4949   }
4950
4951   return (flag==0);
4952 }
4953 #endif
4954
4955
4956 /*-----------------------------------------------------------------*/
4957 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4958 /*                  aop (if it's NOT a literal) or from lit (if    */
4959 /*                  aop is a literal)                              */
4960 /*-----------------------------------------------------------------*/
4961 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4962   if (aop->type == AOP_LIT) {
4963     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4964   } else {
4965     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4966   }
4967 }
4968
4969 /*-----------------------------------------------------------------*/
4970 /* genCmp :- greater or less than comparison                       */
4971 /*-----------------------------------------------------------------*/
4972
4973 #if USE_SIMPLE_GENCMP           /* { */
4974
4975 /* genCmp performs a left < right comparison, stores
4976  * the outcome in result (if != NULL) and generates
4977  * control flow code for the ifx (if != NULL).
4978  *
4979  * This version leaves in sequences like
4980  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4981  * which should be optmized by the peephole
4982  * optimizer - RN 2005-01-01 */
4983 static void genCmp (operand *left,operand *right,
4984                     operand *result, iCode *ifx, int sign)
4985 {
4986   resolvedIfx rIfx;
4987   int size;
4988   int offs;
4989   symbol *templbl;
4990   operand *dummy;
4991   unsigned long lit;
4992   unsigned long mask;
4993   int performedLt;
4994
4995   FENTRY;
4996   
4997   assert (AOP_SIZE(left) == AOP_SIZE(right));
4998   assert (left && right);
4999
5000   size = AOP_SIZE(right) - 1;
5001   mask = (0x100UL << (size*8)) - 1;
5002   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5003   performedLt = 1;
5004   templbl = NULL;
5005   lit = 0;
5006   
5007   resolveIfx (&rIfx, ifx);
5008
5009   /* handle for special cases */
5010   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5011       return;
5012
5013   /**********************************************************************
5014    * handle bits - bit compares are promoted to int compares seemingly! *
5015    **********************************************************************/
5016 #if 0
5017   // THIS IS COMPLETELY UNTESTED!
5018   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5019     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5020     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5021     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5022
5023     emitSETC;
5024     // 1 < {0,1} is false --> clear C by skipping the next instruction
5025     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5026     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5027     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5028     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5029     emitCLRC; // only skipped for left=0 && right=1
5030
5031     goto correct_result_in_carry;
5032   } // if
5033 #endif
5034
5035   /*************************************************
5036    * make sure that left is register (or the like) *
5037    *************************************************/
5038   if (!isAOP_REGlike(left)) {
5039     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5040     assert (isAOP_LIT(left));
5041     assert (isAOP_REGlike(right));
5042     // swap left and right
5043     // left < right <==> right > left <==> (right >= left + 1)
5044     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5045
5046     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5047       // MAXVALUE < right? always false
5048       if (performedLt) emitCLRC; else emitSETC;
5049       goto correct_result_in_carry;
5050     } // if
5051
5052     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5053     // that's why we handled it above.
5054     lit++;
5055
5056     dummy = left;
5057     left = right;
5058     right = dummy;
5059
5060     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5061   } else if (isAOP_LIT(right)) {
5062     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5063   } // if
5064
5065   assert (isAOP_REGlike(left)); // left must be register or the like
5066   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5067
5068   /*************************************************
5069    * special cases go here                         *
5070    *************************************************/
5071
5072   if (isAOP_LIT(right)) {
5073     if (!sign) {
5074       // unsigned comparison to a literal
5075       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5076       if (lit == 0) {
5077         // unsigned left < 0? always false
5078         if (performedLt) emitCLRC; else emitSETC;
5079         goto correct_result_in_carry;
5080       }
5081     } else {
5082       // signed comparison to a literal
5083       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5084       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5085         // signed left < 0x80000000? always false
5086         if (performedLt) emitCLRC; else emitSETC;
5087         goto correct_result_in_carry;
5088       } else if (lit == 0) {
5089         // compare left < 0; set CARRY if SIGNBIT(left) is set
5090         if (performedLt) emitSETC; else emitCLRC;
5091         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5092         if (performedLt) emitCLRC; else emitSETC;
5093         goto correct_result_in_carry;
5094       }
5095     } // if (!sign)
5096   } // right is literal
5097
5098   /*************************************************
5099    * perform a general case comparison             *
5100    * make sure we get CARRY==1 <==> left >= right  *
5101    *************************************************/
5102   // compare most significant bytes
5103   //DEBUGpc ("comparing bytes at offset %d", size);
5104   if (!sign) {
5105     // unsigned comparison
5106     mov2w_regOrLit (AOP(right), lit, size);
5107     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5108   } else {
5109     // signed comparison
5110     // (add 2^n to both operands then perform an unsigned comparison)
5111     if (isAOP_LIT(right)) {
5112       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5113       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5114
5115       if (litbyte == 0x80) {
5116         // left >= 0x80 -- always true, but more bytes to come
5117         pic16_mov2w (AOP(left), size);
5118         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5119         emitSETC;
5120       } else {
5121         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5122         pic16_mov2w (AOP(left), size);
5123         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5124         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5125       } // if
5126     } else {
5127       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5128       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5129       pic16_mov2w (AOP(left), size);
5130       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5131       pic16_emitpcode (POC_MOVWF, pctemp);
5132       pic16_mov2w (AOP(right), size);
5133       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5134       pic16_emitpcode (POC_SUBFW, pctemp);
5135       //pic16_popReleaseTempReg(pctemp, 1);
5136     }
5137   } // if (!sign)
5138
5139   // compare remaining bytes (treat as unsigned case from above)
5140   templbl = newiTempLabel ( NULL );
5141   offs = size;
5142   while (offs--) {
5143     //DEBUGpc ("comparing bytes at offset %d", offs);
5144     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5145     mov2w_regOrLit (AOP(right), lit, offs);
5146     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5147   } // while (offs)
5148   pic16_emitpLabel (templbl->key);
5149   goto result_in_carry;
5150
5151 result_in_carry:
5152   
5153   /****************************************************
5154    * now CARRY contains the result of the comparison: *
5155    * SUBWF sets CARRY iff                             *
5156    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5157    * (F=left, W=right)                                *
5158    ****************************************************/
5159
5160   if (performedLt) {
5161     if (result && AOP_TYPE(result) != AOP_CRY) {
5162       // value will be stored
5163       emitTOGC;
5164     } else {
5165       // value wil only be used in the following genSkipc()
5166       rIfx.condition ^= 1;
5167     }
5168   } // if
5169
5170 correct_result_in_carry:
5171
5172   // assign result to variable (if neccessary)
5173   if (result && AOP_TYPE(result) != AOP_CRY) {
5174     //DEBUGpc ("assign result");
5175     size = AOP_SIZE(result);
5176     while (size--) {
5177       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5178     } // while
5179     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5180   } // if (result)
5181
5182   // perform conditional jump
5183   if (ifx) {
5184     //DEBUGpc ("generate control flow");
5185     genSkipc (&rIfx);
5186     ifx->generated = 1;
5187   } // if
5188 }
5189
5190 #elif 1         /* } */
5191                 /* { */
5192       /* original code */
5193 static void genCmp (operand *left,operand *right,
5194                     operand *result, iCode *ifx, int sign)
5195 {
5196   int size; //, offset = 0 ;
5197   unsigned long lit = 0L,i = 0;
5198   resolvedIfx rFalseIfx;
5199   //  resolvedIfx rTrueIfx;
5200   symbol *truelbl;
5201   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5202 /*
5203   if(ifx) {
5204     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5205     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5206   }
5207 */
5208
5209   FENTRY;
5210   
5211   resolveIfx(&rFalseIfx,ifx);
5212   truelbl  = newiTempLabel(NULL);
5213   size = max(AOP_SIZE(left),AOP_SIZE(right));
5214
5215   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5216
5217 #define _swapp
5218
5219   /* if literal is on the right then swap with left */
5220   if ((AOP_TYPE(right) == AOP_LIT)) {
5221     operand *tmp = right ;
5222     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5223     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5224 #ifdef _swapp
5225
5226     lit = (lit - 1) & mask;
5227     right = left;
5228     left = tmp;
5229     rFalseIfx.condition ^= 1;
5230 #endif
5231
5232   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5233     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5234   }
5235
5236
5237   //if(IC_TRUE(ifx) == NULL)
5238   /* if left & right are bit variables */
5239   if (AOP_TYPE(left) == AOP_CRY &&
5240       AOP_TYPE(right) == AOP_CRY ) {
5241     assert (0 && "bit variables used in genCmp");
5242     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5243     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5244   } else {
5245     /* subtract right from left if at the
5246        end the carry flag is set then we know that
5247        left is greater than right */
5248
5249     symbol *lbl  = newiTempLabel(NULL);
5250
5251 #if 0
5252         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5253                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5254 #endif
5255
5256 #ifndef _swapp
5257     if(AOP_TYPE(right) == AOP_LIT) {
5258
5259       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5260
5261       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5262
5263       /* special cases */
5264
5265       if(lit == 0) {
5266
5267         if(sign != 0) 
5268           genSkipCond(&rFalseIfx,left,size-1,7);
5269         else 
5270           /* no need to compare to 0...*/
5271           /* NOTE: this is a de-generate compare that most certainly 
5272            *       creates some dead code. */
5273           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5274
5275         if(ifx) ifx->generated = 1;
5276         return;
5277
5278       }
5279       size--;
5280
5281       if(size == 0) {
5282         //i = (lit >> (size*8)) & 0xff;
5283         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5284         
5285         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5286
5287         i = ((0-lit) & 0xff);
5288         if(sign) {
5289           if( i == 0x81) { 
5290             /* lit is 0x7f, all signed chars are less than
5291              * this except for 0x7f itself */
5292             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5293             genSkipz2(&rFalseIfx,0);
5294           } else {
5295             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5296             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5297             genSkipc(&rFalseIfx);
5298           }
5299
5300         } else {
5301           if(lit == 1) {
5302             genSkipz2(&rFalseIfx,1);
5303           } else {
5304             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5305             genSkipc(&rFalseIfx);
5306           }
5307         }
5308
5309         if(ifx) ifx->generated = 1;
5310         return;
5311       }
5312
5313       /* chars are out of the way. now do ints and longs */
5314
5315
5316       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5317         
5318       /* special cases */
5319
5320       if(sign) {
5321
5322         if(lit == 0) {
5323           genSkipCond(&rFalseIfx,left,size,7);
5324           if(ifx) ifx->generated = 1;
5325           return;
5326         }
5327
5328         if(lit <0x100) {
5329           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5330
5331           //rFalseIfx.condition ^= 1;
5332           //genSkipCond(&rFalseIfx,left,size,7);
5333           //rFalseIfx.condition ^= 1;
5334
5335           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5336           if(rFalseIfx.condition)
5337             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5338           else
5339             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5340
5341           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5342           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5343           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5344
5345           while(size > 1)
5346             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5347
5348           if(rFalseIfx.condition) {
5349             emitSKPZ;
5350             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5351
5352           } else {
5353             emitSKPNZ;
5354           }
5355
5356           genSkipc(&rFalseIfx);
5357           pic16_emitpLabel(truelbl->key);
5358           if(ifx) ifx->generated = 1;
5359           return;
5360
5361         }
5362
5363         if(size == 1) {
5364
5365           if( (lit & 0xff) == 0) {
5366             /* lower byte is zero */
5367             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5368             i = ((lit >> 8) & 0xff) ^0x80;
5369             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5370             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5371             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5372             genSkipc(&rFalseIfx);
5373
5374
5375             if(ifx) ifx->generated = 1;
5376             return;
5377
5378           }
5379         } else {
5380           /* Special cases for signed longs */
5381           if( (lit & 0xffffff) == 0) {
5382             /* lower byte is zero */
5383             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5384             i = ((lit >> 8*3) & 0xff) ^0x80;
5385             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5386             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5387             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5388             genSkipc(&rFalseIfx);
5389
5390
5391             if(ifx) ifx->generated = 1;
5392             return;
5393
5394           }
5395
5396         }
5397
5398
5399         if(lit & (0x80 << (size*8))) {
5400           /* lit is negative */
5401           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5402
5403           //genSkipCond(&rFalseIfx,left,size,7);
5404
5405           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5406
5407           if(rFalseIfx.condition)
5408             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5409           else
5410             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5411
5412
5413         } else {
5414           /* lit is positive */
5415           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5416           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5417           if(rFalseIfx.condition)
5418             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5419           else
5420             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5421
5422         }
5423
5424         /*
5425           This works, but is only good for ints.
5426           It also requires a "known zero" register.
5427           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5428           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5429           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5430           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5431           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5432           genSkipc(&rFalseIfx);
5433
5434           pic16_emitpLabel(truelbl->key);
5435           if(ifx) ifx->generated = 1;
5436           return;
5437         **/
5438           
5439         /* There are no more special cases, so perform a general compare */
5440   
5441         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5442         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5443
5444         while(size--) {
5445
5446           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5447           emitSKPNZ;
5448           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5449         }
5450         //rFalseIfx.condition ^= 1;
5451         genSkipc(&rFalseIfx);
5452
5453         pic16_emitpLabel(truelbl->key);
5454
5455         if(ifx) ifx->generated = 1;
5456         return;
5457
5458
5459       }
5460
5461
5462       /* sign is out of the way. So now do an unsigned compare */
5463       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5464
5465
5466       /* General case - compare to an unsigned literal on the right.*/
5467
5468       i = (lit >> (size*8)) & 0xff;
5469       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5470       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5471       while(size--) {
5472         i = (lit >> (size*8)) & 0xff;
5473
5474         if(i) {
5475           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5476           emitSKPNZ;
5477           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5478         } else {
5479           /* this byte of the lit is zero, 
5480            *if it's not the last then OR in the variable */
5481           if(size)
5482             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5483         }
5484       }
5485
5486
5487       pic16_emitpLabel(lbl->key);
5488 //      pic16_emitpLabel(truelbl->key);
5489       //if(emitFinalCheck)
5490       genSkipc(&rFalseIfx);
5491       if(sign)
5492         pic16_emitpLabel(truelbl->key);
5493
5494       if(ifx) ifx->generated = 1;
5495       return;
5496
5497
5498     }
5499 #endif  // _swapp
5500
5501     if(AOP_TYPE(left) == AOP_LIT) {
5502       //symbol *lbl = newiTempLabel(NULL);
5503
5504       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5505
5506
5507       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5508
5509       /* Special cases */
5510       if((lit == 0) && (sign == 0)){
5511
5512         size--;
5513         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5514         while(size) 
5515           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5516
5517         genSkipz2(&rFalseIfx,0);
5518         if(ifx) ifx->generated = 1;
5519         return;
5520       }
5521
5522       if(size==1) {
5523         /* Special cases */
5524         lit &= 0xff;
5525         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5526           /* degenerate compare can never be true */
5527           if(rFalseIfx.condition == 0)
5528             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5529
5530           if(ifx) ifx->generated = 1;
5531           return;
5532         }
5533
5534         if(sign) {
5535           /* signed comparisons to a literal byte */
5536
5537           int lp1 = (lit+1) & 0xff;
5538
5539           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5540           switch (lp1) {
5541           case 0:
5542             rFalseIfx.condition ^= 1;
5543             genSkipCond(&rFalseIfx,right,0,7);
5544             break;
5545           case 0x7f:
5546             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5547             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5548             genSkipz2(&rFalseIfx,1);
5549             break;
5550           default:
5551             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5552             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5553             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5554             rFalseIfx.condition ^= 1;
5555             genSkipc(&rFalseIfx);
5556             break;
5557           }
5558         } else {
5559           /* unsigned comparisons to a literal byte */
5560
5561           switch(lit & 0xff ) {
5562           case 0:
5563             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5564             genSkipz2(&rFalseIfx,0);
5565             break;
5566           case 0x7f:
5567             rFalseIfx.condition ^= 1;
5568             genSkipCond(&rFalseIfx,right,0,7);
5569             break;
5570
5571           default:
5572             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5573             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5574             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5575             rFalseIfx.condition ^= 1;
5576             if (AOP_TYPE(result) == AOP_CRY)
5577               genSkipc(&rFalseIfx);
5578             else {
5579               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5580               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5581             }         
5582             break;
5583           }
5584         }
5585
5586         if(ifx) ifx->generated = 1;
5587         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5588                 goto check_carry;
5589         return;
5590
5591       } else {
5592
5593         /* Size is greater than 1 */
5594
5595         if(sign) {
5596           int lp1 = lit+1;
5597
5598           size--;
5599
5600           if(lp1 == 0) {
5601             /* this means lit = 0xffffffff, or -1 */
5602
5603
5604             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5605             rFalseIfx.condition ^= 1;
5606             genSkipCond(&rFalseIfx,right,size,7);
5607             if(ifx) ifx->generated = 1;
5608
5609             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5610               goto check_carry;
5611
5612             return;
5613           }
5614
5615           if(lit == 0) {
5616             int s = size;
5617
5618             if(rFalseIfx.condition) {
5619               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5620               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5621             }
5622
5623             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5624             while(size--)
5625               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5626
5627
5628             emitSKPZ;
5629             if(rFalseIfx.condition) {
5630               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5631               pic16_emitpLabel(truelbl->key);
5632             }else {
5633               rFalseIfx.condition ^= 1;
5634               genSkipCond(&rFalseIfx,right,s,7);
5635             }
5636
5637             if(ifx) ifx->generated = 1;
5638
5639             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5640               goto check_carry;
5641
5642             return;
5643           }
5644
5645           if((size == 1) &&  (0 == (lp1&0xff))) {
5646             /* lower byte of signed word is zero */
5647             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5648             i = ((lp1 >> 8) & 0xff) ^0x80;
5649             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5650             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5651             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5652
5653             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5654               emitTOGC;
5655               if(ifx) ifx->generated = 1;
5656               goto check_carry;
5657             } else {
5658               rFalseIfx.condition ^= 1;
5659               genSkipc(&rFalseIfx);
5660               if(ifx) ifx->generated = 1;
5661             }
5662
5663             return;
5664           }
5665
5666           if(lit & (0x80 << (size*8))) {
5667             /* Lit is less than zero */
5668             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5669             //rFalseIfx.condition ^= 1;
5670             //genSkipCond(&rFalseIfx,left,size,7);
5671             //rFalseIfx.condition ^= 1;
5672             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5673             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5674
5675             if(rFalseIfx.condition)
5676               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5677             else
5678               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5679
5680
5681           } else {
5682             /* Lit is greater than or equal to zero */
5683             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5684             //rFalseIfx.condition ^= 1;
5685             //genSkipCond(&rFalseIfx,right,size,7);
5686             //rFalseIfx.condition ^= 1;
5687
5688             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5689             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5690
5691             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5692             if(rFalseIfx.condition)
5693               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5694             else
5695               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5696
5697           }
5698
5699           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5700           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5701
5702           while(size--) {
5703
5704             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5705             emitSKPNZ;
5706             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5707           }
5708           rFalseIfx.condition ^= 1;
5709           //rFalseIfx.condition = 1;
5710           genSkipc(&rFalseIfx);
5711
5712           pic16_emitpLabel(truelbl->key);
5713
5714           if(ifx) ifx->generated = 1;
5715
5716
5717           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5718             goto check_carry;
5719
5720           return;
5721           // end of if (sign)
5722         } else {
5723
5724           /* compare word or long to an unsigned literal on the right.*/
5725
5726
5727           size--;
5728           if(lit < 0xff) {
5729             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5730             switch (lit) {
5731             case 0:
5732               break; /* handled above */
5733 /*
5734             case 0xff:
5735               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5736               while(size--)
5737                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5738               genSkipz2(&rFalseIfx,0);
5739               break;
5740 */
5741             default:
5742               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5743               while(--size)
5744                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5745
5746               emitSKPZ;
5747               if(rFalseIfx.condition)
5748                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5749               else
5750                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5751
5752
5753               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5754               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5755
5756               rFalseIfx.condition ^= 1;
5757               genSkipc(&rFalseIfx);
5758             }
5759
5760             pic16_emitpLabel(truelbl->key);
5761
5762             if(ifx) ifx->generated = 1;
5763
5764             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5765               goto check_carry;
5766
5767             return;
5768           }
5769
5770
5771           lit++;
5772           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5773           i = (lit >> (size*8)) & 0xff;
5774
5775           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5776           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5777
5778           while(size--) {
5779             i = (lit >> (size*8)) & 0xff;
5780
5781             if(i) {
5782               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5783               emitSKPNZ;
5784               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5785             } else {
5786               /* this byte of the lit is zero, 
5787                * if it's not the last then OR in the variable */
5788               if(size)
5789                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5790             }
5791           }
5792
5793
5794           pic16_emitpLabel(lbl->key);
5795
5796           rFalseIfx.condition ^= 1;
5797
5798           genSkipc(&rFalseIfx);
5799         }
5800
5801         if(sign)
5802           pic16_emitpLabel(truelbl->key);
5803         if(ifx) ifx->generated = 1;
5804
5805             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5806               goto check_carry;
5807
5808         return;
5809       }
5810     }
5811     /* Compare two variables */
5812
5813     DEBUGpic16_emitcode(";sign","%d",sign);
5814
5815     size--;
5816     if(sign) {
5817       /* Sigh. thus sucks... */
5818       if(size) {
5819         pCodeOp *pctemp;
5820         
5821         pctemp = pic16_popGetTempReg(1);
5822         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5823         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5824         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5825         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5826         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5827         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5828         pic16_popReleaseTempReg(pctemp, 1);
5829       } else {
5830         /* Signed char comparison */
5831         /* Special thanks to Nikolai Golovchenko for this snippet */
5832         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5833         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5834         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5835         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5836         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5837         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5838
5839         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5840         genSkipc(&rFalseIfx);
5841           
5842         if(ifx) ifx->generated = 1;
5843
5844             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5845               goto check_carry;
5846
5847         return;
5848       }
5849
5850     } else {
5851
5852       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5853       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5854     }
5855
5856
5857     /* The rest of the bytes of a multi-byte compare */
5858     while (size) {
5859
5860       emitSKPZ;
5861       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5862       size--;
5863
5864       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5865       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5866
5867
5868     }
5869
5870     pic16_emitpLabel(lbl->key);
5871
5872     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5873     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5874         (AOP_TYPE(result) == AOP_REG)) {
5875       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5876       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5877     } else {
5878       genSkipc(&rFalseIfx);
5879     }         
5880     //genSkipc(&rFalseIfx);
5881     if(ifx) ifx->generated = 1;
5882
5883
5884             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5885               goto check_carry;
5886
5887     return;
5888
5889   }
5890
5891 check_carry:
5892   if ((AOP_TYPE(result) != AOP_CRY) 
5893         && AOP_SIZE(result)) {
5894     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5895
5896     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5897
5898     pic16_outBitC(result);
5899   } else {
5900     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5901     /* if the result is used in the next
5902        ifx conditional branch then generate
5903        code a little differently */
5904     if (ifx )
5905       genIfxJump (ifx,"c");
5906     else
5907       pic16_outBitC(result);
5908     /* leave the result in acc */
5909   }
5910
5911 }
5912
5913 #elif 0 /* VR version of genCmp() */    /* } else { */
5914
5915 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5916 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5917         operand *result, int offset, int invert_op)
5918 {
5919   /* add code here */
5920   
5921   /* check condition, > or < ?? */
5922   if(rIfx->condition != 0)invert_op ^= 1;
5923   
5924   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5925
5926   if(!ifx)invert_op ^= 1;
5927
5928   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5929       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5930   
5931   /* do selection */
5932   if(!invert_op)return POC_CPFSGT;
5933   else return POC_CPFSLT;
5934 }
5935
5936 static int compareAopfirstpass=1;
5937
5938 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5939             operand *oper, int offset, operand *result,
5940             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5941             symbol *tlbl)
5942 {
5943   int op;
5944   symbol *truelbl;
5945
5946   /* invert if there is a result to be loaded, in order to fit,
5947    * SETC/CLRC sequence */
5948   if(AOP_SIZE(result))invert_op ^= 1;
5949
5950 //  if(sign && !offset)invert_op ^= 1;
5951   
5952 //  if(sign)invert_op ^= 1;
5953   
5954   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5955
5956   if(AOP_SIZE(result) && compareAopfirstpass) {
5957     if(!ifx) {
5958       if(pcop2)
5959         pic16_emitpcode(POC_SETF, pcop2);
5960       else
5961         emitSETC;
5962     } else {
5963       if(pcop2)
5964         pic16_emitpcode(POC_CLRF, pcop2);
5965       else
5966         emitCLRC;
5967     }
5968   }
5969
5970   compareAopfirstpass = 0;
5971
5972       /* there is a bug when comparing operands with size > 1,
5973        * because higher bytes can be equal and test should be performed
5974        * to the next lower byte, current algorithm, considers operands
5975        * inequal in these cases! -- VR 20041107 */
5976
5977     
5978   if(pcop)
5979     pic16_emitpcode(op, pcop);
5980   else
5981     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5982
5983
5984   if((!sign || !offset) && AOP_SIZE(result)) {
5985     if(!ifx) {
5986       if(pcop2)
5987         pic16_emitpcode(POC_CLRF, pcop2);
5988         else
5989         emitCLRC;
5990     } else {
5991       if(pcop2)
5992         pic16_emitpcode(POC_SETF, pcop2);
5993       else
5994         emitSETC;
5995     }
5996     
5997     /* don't emit final branch (offset == 0) */
5998     if(offset) {
5999
6000       if(pcop2)
6001         pic16_emitpcode(POC_RRCF, pcop2);
6002
6003       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6004     }
6005   } else {
6006     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6007       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6008             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6009
6010       truelbl = newiTempLabel( NULL );
6011       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6012       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6013         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6014       else
6015         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6016       pic16_emitpLabel(truelbl->key);
6017     } else {
6018       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6019     }
6020   }
6021 }
6022
6023 static void genCmp (operand *left, operand *right,
6024                     operand *result, iCode *ifx, int sign)
6025 {
6026   int size, cmpop=1;
6027   long lit = 0L;
6028   resolvedIfx rFalseIfx;
6029   symbol *falselbl, *tlbl;
6030
6031     FENTRY;
6032     
6033     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6034
6035     resolveIfx(&rFalseIfx, ifx);
6036     size = max(AOP_SIZE(left), AOP_SIZE(right));
6037     
6038     /* if left & right are bit variables */
6039     if(AOP_TYPE(left) == AOP_CRY
6040       && AOP_TYPE(right) == AOP_CRY ) {
6041
6042         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6043         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6044         
6045         werror(W_POSSBUG2, __FILE__, __LINE__);
6046         exit(-1);
6047     }
6048     
6049     /* if literal is on the right then swap with left */
6050     if((AOP_TYPE(right) == AOP_LIT)) {
6051       operand *tmp = right ;
6052 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
6053
6054         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6055
6056 //      lit = (lit - 1) & mask;
6057         right = left;
6058         left = tmp;
6059         rFalseIfx.condition ^= 1;               /* reverse compare */
6060     } else
6061     if ((AOP_TYPE(left) == AOP_LIT)) {
6062       /* float compares are handled by support functions */
6063       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6064     }
6065
6066     /* actual comparing algorithm */
6067 //    size = AOP_SIZE( right );
6068
6069     falselbl = newiTempLabel( NULL );
6070     if(AOP_TYPE(left) == AOP_LIT) {
6071       /* compare to literal */
6072       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6073       
6074       if(sign) {
6075         pCodeOp *pct, *pct2;
6076         symbol *tlbl1;
6077
6078         /* signed compare */
6079         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6080
6081         pct = pic16_popCopyReg(&pic16_pc_prodl);
6082         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6083         tlbl = newiTempLabel( NULL );
6084         
6085         /* first compare signs:
6086          *  a. if both are positive, compare just like unsigned
6087          *  b. if both are negative, invert cmpop, compare just like unsigned
6088          *  c. if different signs, determine the result directly */
6089
6090         size--;
6091
6092 #if 1
6093         /* { */
6094         tlbl1 = newiTempLabel( NULL );
6095 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6096
6097         if(lit > 0) {
6098
6099           /* literal is zero or positive:
6100            *  a. if carry is zero, too, continue compare,
6101            *  b. if carry is set, then continue depending on cmpop ^ condition:
6102            *    1. '<' return false (literal < variable),
6103            *    2. '>' return true (literal > variable) */
6104 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6105           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6106           
6107           
6108           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6109           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6110         } else 
6111         if(lit < 0) {
6112           
6113           /* literal is negative:
6114            *  a. if carry is set, too, continue compare,
6115            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6116            *    1. '<' return true (literal < variable),
6117            *    2. '>' return false (literal > variable) */
6118 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6119           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6120           
6121           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6122           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6123         }
6124 #if 1
6125         else {
6126           /* lit == 0 */
6127           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6128           
6129           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6130           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6131         }
6132 #endif
6133         
6134         
6135         pic16_emitpLabel( tlbl1->key );
6136 #endif  /* } */
6137
6138         compareAopfirstpass=1;
6139 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6140 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6141 //        pic16_emitpcode(POC_MOVWF, pct);
6142
6143 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6144         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6145 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6146         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6147
6148         /* generic case */        
6149           while( size-- ) {
6150 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6151 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6152 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6153 //            pic16_emitpcode(POC_MOVWF, pct);
6154
6155 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6156             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6157             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6158 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6159 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6160           }
6161         
6162         if(ifx)ifx->generated = 1;
6163
6164         if(AOP_SIZE(result)) {
6165           pic16_emitpLabel(tlbl->key);
6166           pic16_emitpLabel(falselbl->key);
6167           pic16_outBitOp( result, pct2 );
6168         } else {
6169           pic16_emitpLabel(tlbl->key);
6170         }
6171       } else {
6172
6173         /* unsigned compare */      
6174         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6175     
6176         compareAopfirstpass=1;
6177         while(size--) {
6178           
6179           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6180           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6181
6182         }
6183         if(ifx)ifx->generated = 1;
6184
6185         if(AOP_SIZE(result)) {
6186           pic16_emitpLabel(falselbl->key);
6187           pic16_outBitC( result );
6188         }
6189
6190       }
6191     } else {
6192       /* compare registers */
6193       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6194
6195
6196       if(sign) {
6197         pCodeOp *pct, *pct2;
6198         
6199         /* signed compare */
6200         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6201
6202         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6203         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6204         tlbl = newiTempLabel( NULL );
6205         
6206         compareAopfirstpass=1;
6207
6208         size--;
6209         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6210 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6211         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6212         pic16_emitpcode(POC_MOVWF, pct);
6213
6214         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6215 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6216         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6217
6218         /* WREG already holds left + 0x80 */
6219         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6220         
6221         while( size-- ) {
6222           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6223 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6224           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6225           pic16_emitpcode(POC_MOVWF, pct);
6226                 
6227           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6228 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6229           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6230
6231           /* WREG already holds left + 0x80 */
6232           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6233 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6234         }
6235         
6236         if(ifx)ifx->generated = 1;
6237
6238         if(AOP_SIZE(result)) {
6239           pic16_emitpLabel(tlbl->key);
6240           pic16_emitpLabel(falselbl->key);
6241           pic16_outBitOp( result, pct2 );
6242         } else {
6243           pic16_emitpLabel(tlbl->key);
6244         }
6245
6246       } else {
6247         /* unsigned compare */      
6248         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6249
6250         compareAopfirstpass=1;
6251         while(size--) {
6252           
6253           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6254           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6255
6256         }
6257
6258         if(ifx)ifx->generated = 1;
6259         if(AOP_SIZE(result)) {
6260
6261           pic16_emitpLabel(falselbl->key);
6262           pic16_outBitC( result );
6263         }
6264
6265       }
6266     }
6267 }
6268
6269 #endif  /* } */
6270
6271
6272
6273 /*-----------------------------------------------------------------*/
6274 /* genCmpGt :- greater than comparison                             */
6275 /*-----------------------------------------------------------------*/
6276 static void genCmpGt (iCode *ic, iCode *ifx)
6277 {
6278   operand *left, *right, *result;
6279   sym_link *letype , *retype;
6280   int sign ;
6281
6282     FENTRY;
6283     
6284     left = IC_LEFT(ic);
6285     right= IC_RIGHT(ic);
6286     result = IC_RESULT(ic);
6287
6288     letype = getSpec(operandType(left));
6289     retype =getSpec(operandType(right));
6290     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6291     /* assign the amsops */
6292     pic16_aopOp (left,ic,FALSE);
6293     pic16_aopOp (right,ic,FALSE);
6294     pic16_aopOp (result,ic,TRUE);
6295
6296     genCmp(right, left, result, ifx, sign);
6297
6298     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6299     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6300     pic16_freeAsmop(result,NULL,ic,TRUE); 
6301 }
6302
6303 /*-----------------------------------------------------------------*/
6304 /* genCmpLt - less than comparisons                                */
6305 /*-----------------------------------------------------------------*/
6306 static void genCmpLt (iCode *ic, iCode *ifx)
6307 {
6308   operand *left, *right, *result;
6309   sym_link *letype , *retype;
6310   int sign ;
6311
6312     FENTRY;
6313
6314     left = IC_LEFT(ic);
6315     right= IC_RIGHT(ic);
6316     result = IC_RESULT(ic);
6317
6318     letype = getSpec(operandType(left));
6319     retype =getSpec(operandType(right));
6320     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6321
6322     /* assign the amsops */
6323     pic16_aopOp (left,ic,FALSE);
6324     pic16_aopOp (right,ic,FALSE);
6325     pic16_aopOp (result,ic,TRUE);
6326
6327     genCmp(left, right, result, ifx, sign);
6328
6329     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6330     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6331     pic16_freeAsmop(result,NULL,ic,TRUE); 
6332 }
6333
6334 #if 0
6335 // not needed ATM
6336 // FIXME reenable literal optimisation when the pic16 port is stable
6337
6338 /*-----------------------------------------------------------------*/
6339 /* genc16bit2lit - compare a 16 bit value to a literal             */
6340 /*-----------------------------------------------------------------*/
6341 static void genc16bit2lit(operand *op, int lit, int offset)
6342 {
6343   int i;
6344
6345   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6346   if( (lit&0xff) == 0) 
6347     i=1;
6348   else
6349     i=0;
6350
6351   switch( BYTEofLONG(lit,i)) { 
6352   case 0:
6353     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6354     break;
6355   case 1:
6356     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6357     break;
6358   case 0xff:
6359     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6360     break;
6361   default:
6362     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6363     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6364   }
6365
6366   i ^= 1;
6367
6368   switch( BYTEofLONG(lit,i)) { 
6369   case 0:
6370     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6371     break;
6372   case 1:
6373     emitSKPNZ;
6374     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6375     break;
6376   case 0xff:
6377     emitSKPNZ;
6378     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6379     break;
6380   default:
6381     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6382     emitSKPNZ;
6383     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6384
6385   }
6386
6387 }
6388 #endif
6389
6390 #if 0
6391 // not needed ATM
6392 /*-----------------------------------------------------------------*/
6393 /* gencjneshort - compare and jump if not equal                    */
6394 /*-----------------------------------------------------------------*/
6395 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6396 {
6397   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6398   int offset = 0;
6399   int res_offset = 0;  /* the result may be a different size then left or right */
6400   int res_size = AOP_SIZE(result);
6401   resolvedIfx rIfx;
6402   symbol *lbl, *lbl_done;
6403
6404   unsigned long lit = 0L;
6405   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6406
6407   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6408   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6409   if(result)
6410     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6411   resolveIfx(&rIfx,ifx);
6412   lbl =  newiTempLabel(NULL);
6413   lbl_done =  newiTempLabel(NULL);
6414
6415
6416   /* if the left side is a literal or 
6417      if the right is in a pointer register and left 
6418      is not */
6419   if ((AOP_TYPE(left) == AOP_LIT) || 
6420       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6421     operand *t = right;
6422     right = left;
6423     left = t;
6424   }
6425   if(AOP_TYPE(right) == AOP_LIT)
6426     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6427
6428   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6429     preserve_result = 1;
6430
6431   if(result && !preserve_result)
6432     {
6433       int i;
6434       for(i = 0; i < AOP_SIZE(result); i++)
6435         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6436     }
6437
6438
6439   /* if the right side is a literal then anything goes */
6440   if (AOP_TYPE(right) == AOP_LIT &&
6441       AOP_TYPE(left) != AOP_DIR ) {
6442     switch(size) {
6443     case 2:
6444       genc16bit2lit(left, lit, 0);
6445       emitSKPZ;
6446       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6447       break;
6448     default:
6449       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6450       while (size--) {
6451         if(lit & 0xff) {
6452           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6453           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6454         } else {
6455           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6456         }
6457
6458         emitSKPZ;
6459         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6460         offset++;
6461         if(res_offset < res_size-1)
6462           res_offset++;
6463         lit >>= 8;
6464       }
6465       break;
6466     }
6467   }
6468
6469   /* if the right side is in a register or in direct space or
6470      if the left is a pointer register & right is not */    
6471   else if (AOP_TYPE(right) == AOP_REG ||
6472            AOP_TYPE(right) == AOP_DIR || 
6473            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6474            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6475     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6476     int lbl_key = lbl->key;
6477
6478     if(result) {
6479       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6480       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6481     }else {
6482       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6483       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6484               __FUNCTION__,__LINE__);
6485       return;
6486     }
6487    
6488 /*     switch(size) { */
6489 /*     case 2: */
6490 /*       genc16bit2lit(left, lit, 0); */
6491 /*       emitSKPNZ; */
6492 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6493 /*       break; */
6494 /*     default: */
6495     while (size--) {
6496       int emit_skip=1;
6497       if((AOP_TYPE(left) == AOP_DIR) && 
6498          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6499
6500         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6501         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6502
6503       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6504             
6505         switch (lit & 0xff) {
6506         case 0:
6507           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6508           break;
6509         case 1:
6510           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6511           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6512           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6513           emit_skip=0;
6514           break;
6515         case 0xff:
6516           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6517           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6518           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6519           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6520           emit_skip=0;
6521           break;
6522         default:
6523           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6524           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6525         }
6526         lit >>= 8;
6527
6528       } else {
6529         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6530       }
6531       if(emit_skip) {
6532         if(AOP_TYPE(result) == AOP_CRY) {
6533           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6534           if(rIfx.condition)
6535             emitSKPNZ;
6536           else
6537             emitSKPZ;
6538           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6539         } else {
6540           /* fix me. probably need to check result size too */
6541           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6542           if(rIfx.condition)
6543             emitSKPZ;
6544           else
6545             emitSKPNZ;
6546           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6547           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6548         }
6549         if(ifx)
6550           ifx->generated=1;
6551       }
6552       emit_skip++;
6553       offset++;
6554       if(res_offset < res_size-1)
6555         res_offset++;
6556     }
6557 /*       break; */
6558 /*     } */
6559   } else if(AOP_TYPE(right) == AOP_REG &&
6560             AOP_TYPE(left) != AOP_DIR){
6561
6562     while(size--) {
6563       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6564       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6565       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6566       if(rIfx.condition)
6567         emitSKPNZ;
6568       else
6569         emitSKPZ;
6570       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6571       offset++;
6572       if(res_offset < res_size-1)
6573         res_offset++;
6574     }
6575       
6576   }else{
6577     /* right is a pointer reg need both a & b */
6578     while(size--) {
6579       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6580       if(strcmp(l,"b"))
6581         pic16_emitcode("mov","b,%s",l);
6582       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6583       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6584       offset++;
6585     }
6586   }
6587
6588   if(result && preserve_result)
6589     {
6590       int i;
6591       for(i = 0; i < AOP_SIZE(result); i++)
6592         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6593     }
6594
6595   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6596
6597   if(result && preserve_result)
6598     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6599
6600   if(!rIfx.condition)
6601     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6602
6603   pic16_emitpLabel(lbl->key);
6604
6605   if(result && preserve_result)
6606     {
6607       int i;
6608       for(i = 0; i < AOP_SIZE(result); i++)
6609         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6610
6611       pic16_emitpLabel(lbl_done->key);
6612    }
6613
6614   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6615
6616   if(ifx)
6617     ifx->generated = 1;
6618 }
6619 #endif
6620
6621 #if 0
6622 /*-----------------------------------------------------------------*/
6623 /* gencjne - compare and jump if not equal                         */
6624 /*-----------------------------------------------------------------*/
6625 static void gencjne(operand *left, operand *right, iCode *ifx)
6626 {
6627     symbol *tlbl  = newiTempLabel(NULL);
6628
6629     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6630     gencjneshort(left, right, lbl);
6631
6632     pic16_emitcode("mov","a,%s",one);
6633     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6634     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6635     pic16_emitcode("clr","a");
6636     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6637
6638     pic16_emitpLabel(lbl->key);
6639     pic16_emitpLabel(tlbl->key);
6640
6641 }
6642 #endif
6643
6644
6645 /*-----------------------------------------------------------------*/
6646 /* is_LitOp - check if operand has to be treated as literal        */
6647 /*-----------------------------------------------------------------*/
6648 static bool is_LitOp(operand *op)
6649 {
6650   return ((AOP_TYPE(op) == AOP_LIT)
6651       || ( (AOP_TYPE(op) == AOP_PCODE)
6652           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6653               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6654 }
6655
6656 /*-----------------------------------------------------------------*/
6657 /* is_LitAOp - check if operand has to be treated as literal        */
6658 /*-----------------------------------------------------------------*/
6659 static bool is_LitAOp(asmop *aop)
6660 {
6661   return ((aop->type == AOP_LIT)
6662       || ( (aop->type == AOP_PCODE)
6663           && ( (aop->aopu.pcop->type == PO_LITERAL)
6664               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6665 }
6666
6667
6668
6669 /*-----------------------------------------------------------------*/
6670 /* genCmpEq - generates code for equal to                          */
6671 /*-----------------------------------------------------------------*/
6672 static void genCmpEq (iCode *ic, iCode *ifx)
6673 {
6674   operand *left, *right, *result;
6675   symbol *falselbl = newiTempLabel(NULL);
6676   symbol *donelbl = newiTempLabel(NULL);
6677
6678   int preserve_result = 0;
6679   int generate_result = 0;
6680   int i=0;
6681   unsigned long lit = -1;
6682
6683   FENTRY;
6684   
6685   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6686   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6687   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6688  
6689   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6690
6691   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6692     {
6693       werror(W_POSSBUG2, __FILE__, __LINE__);
6694       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6695       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6696       goto release;
6697     }
6698
6699   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6700     {
6701       operand *tmp = right ;
6702       right = left;
6703       left = tmp;
6704     }
6705
6706   if (AOP_TYPE(right) == AOP_LIT) {
6707     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6708   }
6709
6710   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6711     preserve_result = 1;
6712
6713   if(result && AOP_SIZE(result))
6714     generate_result = 1;
6715
6716   if(generate_result && !preserve_result)
6717     {
6718       for(i = 0; i < AOP_SIZE(result); i++)
6719         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6720     }
6721
6722   for(i=0; i < AOP_SIZE(left); i++)
6723     {
6724       if(AOP_TYPE(left) != AOP_ACC)
6725         {
6726           if(is_LitOp(left))
6727             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6728           else
6729             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6730         }
6731       if(is_LitOp(right)) {
6732         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6733           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6734         }
6735       } else
6736         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6737
6738       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6739     }
6740
6741   // result == true
6742
6743   if(generate_result && preserve_result)
6744     {
6745       for(i = 0; i < AOP_SIZE(result); i++)
6746         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6747     }
6748
6749   if(generate_result)
6750     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6751
6752   if(generate_result && preserve_result)
6753     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6754
6755   if(ifx && IC_TRUE(ifx))
6756     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6757
6758   if(ifx && IC_FALSE(ifx))
6759     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6760
6761   pic16_emitpLabel(falselbl->key);
6762
6763   // result == false
6764
6765   if(ifx && IC_FALSE(ifx))
6766     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6767
6768   if(generate_result && preserve_result)
6769     {
6770       for(i = 0; i < AOP_SIZE(result); i++)
6771         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6772     }
6773
6774   pic16_emitpLabel(donelbl->key);
6775
6776   if(ifx)
6777     ifx->generated = 1;
6778
6779 release:
6780   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6781   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6782   pic16_freeAsmop(result,NULL,ic,TRUE);
6783
6784 }
6785
6786
6787 #if 0
6788 // old version kept for reference
6789
6790 /*-----------------------------------------------------------------*/
6791 /* genCmpEq - generates code for equal to                          */
6792 /*-----------------------------------------------------------------*/
6793 static void genCmpEq (iCode *ic, iCode *ifx)
6794 {
6795     operand *left, *right, *result;
6796     unsigned long lit = 0L;
6797     int size,offset=0;
6798     symbol *falselbl  = newiTempLabel(NULL);
6799
6800
6801     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6802
6803     if(ifx)
6804       DEBUGpic16_emitcode ("; ifx is non-null","");
6805     else
6806       DEBUGpic16_emitcode ("; ifx is null","");
6807
6808     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6809     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6810     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6811
6812     size = max(AOP_SIZE(left),AOP_SIZE(right));
6813
6814     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6815
6816     /* if literal, literal on the right or 
6817     if the right is in a pointer register and left 
6818     is not */
6819     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6820         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6821       operand *tmp = right ;
6822       right = left;
6823       left = tmp;
6824     }
6825
6826
6827     if(ifx && !AOP_SIZE(result)){
6828         symbol *tlbl;
6829         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6830         /* if they are both bit variables */
6831         if (AOP_TYPE(left) == AOP_CRY &&
6832             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6833                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6834             if(AOP_TYPE(right) == AOP_LIT){
6835                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6836                 if(lit == 0L){
6837                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6838                     pic16_emitcode("cpl","c");
6839                 } else if(lit == 1L) {
6840                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6841                 } else {
6842                     pic16_emitcode("clr","c");
6843                 }
6844                 /* AOP_TYPE(right) == AOP_CRY */
6845             } else {
6846                 symbol *lbl = newiTempLabel(NULL);
6847                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6848                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6849                 pic16_emitcode("cpl","c");
6850                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6851             }
6852             /* if true label then we jump if condition
6853             supplied is true */
6854             tlbl = newiTempLabel(NULL);
6855             if ( IC_TRUE(ifx) ) {
6856                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6857                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6858             } else {
6859                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6860                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6861             }
6862             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6863
6864                 {
6865                 /* left and right are both bit variables, result is carry */
6866                         resolvedIfx rIfx;
6867               
6868                         resolveIfx(&rIfx,ifx);
6869
6870                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6871                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6872                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6873                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6874                         genSkipz2(&rIfx,0);
6875                 }
6876         } else {
6877
6878                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6879
6880                         /* They're not both bit variables. Is the right a literal? */
6881                         if(AOP_TYPE(right) == AOP_LIT) {
6882                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6883             
6884                         switch(size) {
6885
6886                                 case 1:
6887                                         switch(lit & 0xff) {
6888                                                 case 1:
6889                                                                 if ( IC_TRUE(ifx) ) {
6890                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6891                                                                         emitSKPNZ;
6892                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6893                                                                 } else {
6894                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6895                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6896                                                                 }
6897                                                                 break;
6898                                                 case 0xff:
6899                                                                 if ( IC_TRUE(ifx) ) {
6900                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6901                                                                         emitSKPNZ;
6902                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6903                                                                 } else {
6904                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6905                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6906                                                                 }
6907                                                                 break;
6908                                                 default:
6909                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6910                                                                 if(lit)
6911                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6912                                                                 genSkip(ifx,'z');
6913                                         } // switch lit
6914
6915
6916                                         /* end of size == 1 */
6917                                         break;
6918               
6919                                 case 2:
6920                                         genc16bit2lit(left,lit,offset);
6921                                         genSkip(ifx,'z');
6922                                         break;
6923                                         /* end of size == 2 */
6924
6925                                 default:
6926                                         /* size is 4 */
6927                                         if(lit==0) {
6928                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6929                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6930                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6931                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6932                                                 genSkip(ifx,'z');
6933                                         } else {
6934                                                 /* search for patterns that can be optimized */
6935
6936                                                 genc16bit2lit(left,lit,0);
6937                                                 lit >>= 16;
6938                                                 if(lit) {
6939                                                                 if(IC_TRUE(ifx))
6940                                                                 emitSKPZ; // if hi word unequal
6941                                                                 else
6942                                                                 emitSKPNZ; // if hi word equal
6943                                                                 // fail early
6944                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6945                                                         genc16bit2lit(left,lit,2);
6946                                                         genSkip(ifx,'z');
6947                                                 } else {
6948                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6949                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6950                                                         genSkip(ifx,'z');
6951                                                 }
6952                                         }
6953                                                 pic16_emitpLabel(falselbl->key);
6954                                                 break;
6955
6956                         } // switch size
6957           
6958                         ifx->generated = 1;
6959                         goto release ;
6960             
6961
6962           } else if(AOP_TYPE(right) == AOP_CRY ) {
6963             /* we know the left is not a bit, but that the right is */
6964             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6965             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6966                       pic16_popGet(AOP(right),offset));
6967             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6968
6969             /* if the two are equal, then W will be 0 and the Z bit is set
6970              * we could test Z now, or go ahead and check the high order bytes if
6971              * the variable we're comparing is larger than a byte. */
6972
6973             while(--size)
6974               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6975
6976             if ( IC_TRUE(ifx) ) {
6977               emitSKPNZ;
6978               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6979               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6980             } else {
6981               emitSKPZ;
6982               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6983               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6984             }
6985
6986           } else {
6987             /* They're both variables that are larger than bits */
6988             int s = size;
6989
6990             tlbl = newiTempLabel(NULL);
6991
6992             while(size--) {
6993               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6994               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6995
6996               if ( IC_TRUE(ifx) ) {
6997                 if(size) {
6998                   emitSKPZ;
6999                 
7000                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7001
7002                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7003                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7004                 } else {
7005                   emitSKPNZ;
7006
7007                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7008
7009
7010                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7011                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7012                 }
7013               } else {
7014                 emitSKPZ;
7015
7016                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7017
7018                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7019                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7020               }
7021               offset++;
7022             }
7023             if(s>1 && IC_TRUE(ifx)) {
7024               pic16_emitpLabel(tlbl->key);
7025               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7026             }
7027           }
7028         }
7029         /* mark the icode as generated */
7030         ifx->generated = 1;
7031         goto release ;
7032     }
7033
7034     /* if they are both bit variables */
7035     if (AOP_TYPE(left) == AOP_CRY &&
7036         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7037         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7038         if(AOP_TYPE(right) == AOP_LIT){
7039             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7040             if(lit == 0L){
7041                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7042                 pic16_emitcode("cpl","c");
7043             } else if(lit == 1L) {
7044                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7045             } else {
7046                 pic16_emitcode("clr","c");
7047             }
7048             /* AOP_TYPE(right) == AOP_CRY */
7049         } else {
7050             symbol *lbl = newiTempLabel(NULL);
7051             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7052             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7053             pic16_emitcode("cpl","c");
7054             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7055         }
7056         /* c = 1 if egal */
7057         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7058             pic16_outBitC(result);
7059             goto release ;
7060         }
7061         if (ifx) {
7062             genIfxJump (ifx,"c");
7063             goto release ;
7064         }
7065         /* if the result is used in an arithmetic operation
7066         then put the result in place */
7067         pic16_outBitC(result);
7068     } else {
7069       
7070       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7071       gencjne(left,right,result,ifx);
7072 /*
7073       if(ifx) 
7074         gencjne(left,right,newiTempLabel(NULL));
7075       else {
7076         if(IC_TRUE(ifx)->key)
7077           gencjne(left,right,IC_TRUE(ifx)->key);
7078         else
7079           gencjne(left,right,IC_FALSE(ifx)->key);
7080         ifx->generated = 1;
7081         goto release ;
7082       }
7083       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7084         pic16_aopPut(AOP(result),"a",0);
7085         goto release ;
7086       }
7087
7088       if (ifx) {
7089         genIfxJump (ifx,"a");
7090         goto release ;
7091       }
7092 */
7093       /* if the result is used in an arithmetic operation
7094          then put the result in place */
7095 /*
7096       if (AOP_TYPE(result) != AOP_CRY) 
7097         pic16_outAcc(result);
7098 */
7099       /* leave the result in acc */
7100     }
7101
7102 release:
7103     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7104     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7105     pic16_freeAsmop(result,NULL,ic,TRUE);
7106 }
7107 #endif
7108
7109 /*-----------------------------------------------------------------*/
7110 /* ifxForOp - returns the icode containing the ifx for operand     */
7111 /*-----------------------------------------------------------------*/
7112 static iCode *ifxForOp ( operand *op, iCode *ic )
7113 {
7114   FENTRY2;
7115
7116     /* if true symbol then needs to be assigned */
7117     if (IS_TRUE_SYMOP(op))
7118         return NULL ;
7119
7120     /* if this has register type condition and
7121     the next instruction is ifx with the same operand
7122     and live to of the operand is upto the ifx only then */
7123     if (ic->next
7124         && ic->next->op == IFX
7125         && IC_COND(ic->next)->key == op->key
7126         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7127         ) {
7128                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7129           return ic->next;
7130     }
7131
7132     /*
7133     if (ic->next &&
7134         ic->next->op == IFX &&
7135         IC_COND(ic->next)->key == op->key) {
7136       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7137       return ic->next;
7138     }
7139     */
7140
7141     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7142     if (ic->next &&
7143         ic->next->op == IFX)
7144       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7145
7146     if (ic->next &&
7147         ic->next->op == IFX &&
7148         IC_COND(ic->next)->key == op->key) {
7149       DEBUGpic16_emitcode ("; "," key is okay");
7150       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7151                            OP_SYMBOL(op)->liveTo,
7152                            ic->next->seq);
7153     }
7154
7155 #if 0
7156     /* the code below is completely untested
7157      * it just allows ulong2fs.c compile -- VR */
7158          
7159     ic = ic->next;
7160     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7161                                         __FILE__, __FUNCTION__, __LINE__);
7162         
7163     /* if this has register type condition and
7164     the next instruction is ifx with the same operand
7165     and live to of the operand is upto the ifx only then */
7166     if (ic->next &&
7167         ic->next->op == IFX &&
7168         IC_COND(ic->next)->key == op->key &&
7169         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7170         return ic->next;
7171
7172     if (ic->next &&
7173         ic->next->op == IFX &&
7174         IC_COND(ic->next)->key == op->key) {
7175       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7176       return ic->next;
7177     }
7178
7179     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7180                                         __FILE__, __FUNCTION__, __LINE__);
7181
7182 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7183 #endif
7184
7185     return NULL;
7186 }
7187 /*-----------------------------------------------------------------*/
7188 /* genAndOp - for && operation                                     */
7189 /*-----------------------------------------------------------------*/
7190 static void genAndOp (iCode *ic)
7191 {
7192   operand *left,*right, *result;
7193 /*     symbol *tlbl; */
7194
7195     FENTRY;
7196
7197     /* note here that && operations that are in an
7198     if statement are taken away by backPatchLabels
7199     only those used in arthmetic operations remain */
7200     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7201     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7202     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7203
7204     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7205
7206     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7207     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7208     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7209
7210     /* if both are bit variables */
7211 /*     if (AOP_TYPE(left) == AOP_CRY && */
7212 /*         AOP_TYPE(right) == AOP_CRY ) { */
7213 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7214 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7215 /*         pic16_outBitC(result); */
7216 /*     } else { */
7217 /*         tlbl = newiTempLabel(NULL); */
7218 /*         pic16_toBoolean(left);     */
7219 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7220 /*         pic16_toBoolean(right); */
7221 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7222 /*         pic16_outBitAcc(result); */
7223 /*     } */
7224
7225     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7226     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7227     pic16_freeAsmop(result,NULL,ic,TRUE);
7228 }
7229
7230
7231 /*-----------------------------------------------------------------*/
7232 /* genOrOp - for || operation                                      */
7233 /*-----------------------------------------------------------------*/
7234 /*
7235   tsd pic port -
7236   modified this code, but it doesn't appear to ever get called
7237 */
7238
7239 static void genOrOp (iCode *ic)
7240 {
7241   operand *left,*right, *result;
7242   symbol *tlbl;
7243
7244     FENTRY;  
7245
7246   /* note here that || operations that are in an
7247     if statement are taken away by backPatchLabels
7248     only those used in arthmetic operations remain */
7249     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7250     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7251     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7252
7253     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7254
7255     /* if both are bit variables */
7256     if (AOP_TYPE(left) == AOP_CRY &&
7257         AOP_TYPE(right) == AOP_CRY ) {
7258       pic16_emitcode("clrc","");
7259       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7260                AOP(left)->aopu.aop_dir,
7261                AOP(left)->aopu.aop_dir);
7262       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7263                AOP(right)->aopu.aop_dir,
7264                AOP(right)->aopu.aop_dir);
7265       pic16_emitcode("setc","");
7266
7267     } else {
7268         tlbl = newiTempLabel(NULL);
7269         pic16_toBoolean(left);
7270         emitSKPZ;
7271         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7272         pic16_toBoolean(right);
7273         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7274
7275         pic16_outBitAcc(result);
7276     }
7277
7278     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7279     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7280     pic16_freeAsmop(result,NULL,ic,TRUE);            
7281 }
7282
7283 /*-----------------------------------------------------------------*/
7284 /* isLiteralBit - test if lit == 2^n                               */
7285 /*-----------------------------------------------------------------*/
7286 static int isLiteralBit(unsigned long lit)
7287 {
7288     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7289     0x100L,0x200L,0x400L,0x800L,
7290     0x1000L,0x2000L,0x4000L,0x8000L,
7291     0x10000L,0x20000L,0x40000L,0x80000L,
7292     0x100000L,0x200000L,0x400000L,0x800000L,
7293     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7294     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7295     int idx;
7296     
7297     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7298     for(idx = 0; idx < 32; idx++)
7299         if(lit == pw[idx])
7300             return idx+1;
7301     return 0;
7302 }
7303
7304 /*-----------------------------------------------------------------*/
7305 /* continueIfTrue -                                                */
7306 /*-----------------------------------------------------------------*/
7307 static void continueIfTrue (iCode *ic)
7308 {
7309   FENTRY;
7310   if(IC_TRUE(ic))
7311     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7312   ic->generated = 1;
7313 }
7314
7315 /*-----------------------------------------------------------------*/
7316 /* jmpIfTrue -                                                     */
7317 /*-----------------------------------------------------------------*/
7318 static void jumpIfTrue (iCode *ic)
7319 {
7320   FENTRY;
7321   if(!IC_TRUE(ic))
7322     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7323   ic->generated = 1;
7324 }
7325
7326 /*-----------------------------------------------------------------*/
7327 /* jmpTrueOrFalse -                                                */
7328 /*-----------------------------------------------------------------*/
7329 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7330 {
7331   // ugly but optimized by peephole
7332   FENTRY;
7333   if(IC_TRUE(ic)){
7334     symbol *nlbl = newiTempLabel(NULL);
7335       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7336       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7337       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7338       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7339   } else {
7340     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7341     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7342   }
7343   ic->generated = 1;
7344 }
7345
7346 /*-----------------------------------------------------------------*/
7347 /* genAnd  - code for and                                          */
7348 /*-----------------------------------------------------------------*/
7349 static void genAnd (iCode *ic, iCode *ifx)
7350 {
7351   operand *left, *right, *result;
7352   int size, offset=0;  
7353   unsigned long lit = 0L;
7354   int bytelit = 0;
7355   resolvedIfx rIfx;
7356
7357     FENTRY;
7358     
7359   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7360   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7361   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7362
7363   resolveIfx(&rIfx,ifx);
7364
7365   /* if left is a literal & right is not then exchange them */
7366   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7367       AOP_NEEDSACC(left)) {
7368     operand *tmp = right ;
7369     right = left;
7370     left = tmp;
7371   }
7372
7373   /* if result = right then exchange them */
7374   if(pic16_sameRegs(AOP(result),AOP(right))){
7375     operand *tmp = right ;
7376     right = left;
7377     left = tmp;
7378   }
7379
7380   /* if right is bit then exchange them */
7381   if (AOP_TYPE(right) == AOP_CRY &&
7382       AOP_TYPE(left) != AOP_CRY){
7383     operand *tmp = right ;
7384     right = left;
7385     left = tmp;
7386   }
7387   if(AOP_TYPE(right) == AOP_LIT)
7388     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7389
7390   size = AOP_SIZE(result);
7391
7392   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7393
7394   // if(bit & yy)
7395   // result = bit & yy;
7396   if (AOP_TYPE(left) == AOP_CRY){
7397     // c = bit & literal;
7398     if(AOP_TYPE(right) == AOP_LIT){
7399       if(lit & 1) {
7400         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7401           // no change
7402           goto release;
7403         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7404       } else {
7405         // bit(result) = 0;
7406         if(size && (AOP_TYPE(result) == AOP_CRY)){
7407           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7408           goto release;
7409         }
7410         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7411           jumpIfTrue(ifx);
7412           goto release;
7413         }
7414         pic16_emitcode("clr","c");
7415       }
7416     } else {
7417       if (AOP_TYPE(right) == AOP_CRY){
7418         // c = bit & bit;
7419         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7420         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7421       } else {
7422         // c = bit & val;
7423         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7424         // c = lsb
7425         pic16_emitcode("rrc","a");
7426         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7427       }
7428     }
7429     // bit = c
7430     // val = c
7431     if(size)
7432       pic16_outBitC(result);
7433     // if(bit & ...)
7434     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7435       genIfxJump(ifx, "c");           
7436     goto release ;
7437   }
7438
7439   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7440   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7441   if((AOP_TYPE(right) == AOP_LIT) &&
7442      (AOP_TYPE(result) == AOP_CRY) &&
7443      (AOP_TYPE(left) != AOP_CRY)){
7444     int posbit = isLiteralBit(lit);
7445     /* left &  2^n */
7446     if(posbit){
7447       posbit--;
7448       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7449       // bit = left & 2^n
7450       if(size)
7451         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7452       // if(left &  2^n)
7453       else{
7454         if(ifx){
7455 /*
7456           if(IC_TRUE(ifx)) {
7457             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7458             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7459           } else {
7460             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7461             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7462           }
7463 */
7464         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7465         size = AOP_SIZE(left);
7466
7467         {
7468           int bp = posbit, ofs=0;
7469           
7470             while(bp > 7) {
7471               bp -= 8;
7472               ofs++;
7473             }
7474
7475           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7476                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7477
7478         }
7479 /*
7480           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7481                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7482 */
7483           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7484           
7485           ifx->generated = 1;
7486         }
7487         goto release;
7488       }
7489     } else {
7490       symbol *tlbl = newiTempLabel(NULL);
7491       int sizel = AOP_SIZE(left);
7492
7493       if(size)
7494         emitSETC;
7495
7496       while(sizel--) {
7497         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7498
7499           /* patch provided by Aaron Colwell */
7500           if((posbit = isLiteralBit(bytelit)) != 0) {
7501               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7502                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7503                                                 (posbit-1),0, PO_GPR_REGISTER));
7504
7505               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7506 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7507           } else {
7508               if (bytelit == 0xff) {
7509                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7510                    * a peephole could optimize it out -- VR */
7511                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7512               } else {
7513                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7514                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7515               }
7516
7517               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7518                             pic16_popGetLabel(tlbl->key));
7519           }
7520         
7521 #if 0
7522           /* old code, left here for reference -- VR 09/2004 */
7523           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7524           // byte ==  2^n ?
7525           if((posbit = isLiteralBit(bytelit)) != 0)
7526             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7527           else{
7528             if(bytelit != 0x0FFL)
7529               pic16_emitcode("anl","a,%s",
7530                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7531             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7532           }
7533 #endif
7534         }
7535         offset++;
7536       }
7537       // bit = left & literal
7538       if(size) {
7539         emitCLRC;
7540         pic16_emitpLabel(tlbl->key);
7541       }
7542       // if(left & literal)
7543       else {
7544         if(ifx) {
7545           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7546           ifx->generated = 1;
7547         }
7548         pic16_emitpLabel(tlbl->key);
7549         goto release;
7550       }
7551     }
7552
7553     pic16_outBitC(result);
7554     goto release ;
7555   }
7556
7557   /* if left is same as result */
7558   if(pic16_sameRegs(AOP(result),AOP(left))){
7559     int know_W = -1;
7560     for(;size--; offset++,lit>>=8) {
7561       if(AOP_TYPE(right) == AOP_LIT){
7562         switch(lit & 0xff) {
7563         case 0x00:
7564           /*  and'ing with 0 has clears the result */
7565 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7566           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7567           break;
7568         case 0xff:
7569           /* and'ing with 0xff is a nop when the result and left are the same */
7570           break;
7571
7572         default:
7573           {
7574             int p = pic16_my_powof2( (~lit) & 0xff );
7575             if(p>=0) {
7576               /* only one bit is set in the literal, so use a bcf instruction */
7577 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7578               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7579
7580             } else {
7581               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7582               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7583               if(know_W != (lit&0xff))
7584                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7585               know_W = lit &0xff;
7586               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7587             }
7588           }    
7589         }
7590       } else {
7591         if (AOP_TYPE(left) == AOP_ACC) {
7592           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7593         } else {                    
7594           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7595           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7596
7597         }
7598       }
7599     }
7600
7601   } else {
7602     // left & result in different registers
7603     if(AOP_TYPE(result) == AOP_CRY){
7604       // result = bit
7605       // if(size), result in bit
7606       // if(!size && ifx), conditional oper: if(left & right)
7607       symbol *tlbl = newiTempLabel(NULL);
7608       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7609       if(size)
7610         pic16_emitcode("setb","c");
7611       while(sizer--){
7612         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7613         pic16_emitcode("anl","a,%s",
7614                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7615         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7616         offset++;
7617       }
7618       if(size){
7619         CLRC;
7620         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7621         pic16_outBitC(result);
7622       } else if(ifx)
7623         jmpTrueOrFalse(ifx, tlbl);
7624     } else {
7625       for(;(size--);offset++) {
7626         // normal case
7627         // result = left & right
7628         if(AOP_TYPE(right) == AOP_LIT){
7629           int t = (lit >> (offset*8)) & 0x0FFL;
7630           switch(t) { 
7631           case 0x00:
7632             pic16_emitcode("clrf","%s",
7633                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7634             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7635             break;
7636           case 0xff:
7637             pic16_emitcode("movf","%s,w",
7638                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7639             pic16_emitcode("movwf","%s",
7640                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7641             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7642             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7643             break;
7644           default:
7645             pic16_emitcode("movlw","0x%x",t);
7646             pic16_emitcode("andwf","%s,w",
7647                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7648             pic16_emitcode("movwf","%s",
7649                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7650               
7651             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7652             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7653             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7654           }
7655           continue;
7656         }
7657
7658         if (AOP_TYPE(left) == AOP_ACC) {
7659           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7660           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7661         } else {
7662           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7663           pic16_emitcode("andwf","%s,w",
7664                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7665           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7666           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7667         }
7668         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7669         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7670       }
7671     }
7672   }
7673
7674   release :
7675     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7676   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7677   pic16_freeAsmop(result,NULL,ic,TRUE);     
7678 }
7679
7680 /*-----------------------------------------------------------------*/
7681 /* genOr  - code for or                                            */
7682 /*-----------------------------------------------------------------*/
7683 static void genOr (iCode *ic, iCode *ifx)
7684 {
7685     operand *left, *right, *result;
7686     int size, offset=0;
7687     unsigned long lit = 0L;
7688
7689     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7690
7691     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7692     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7693     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7694
7695     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7696
7697     /* if left is a literal & right is not then exchange them */
7698     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7699         AOP_NEEDSACC(left)) {
7700         operand *tmp = right ;
7701         right = left;
7702         left = tmp;
7703     }
7704
7705     /* if result = right then exchange them */
7706     if(pic16_sameRegs(AOP(result),AOP(right))){
7707         operand *tmp = right ;
7708         right = left;
7709         left = tmp;
7710     }
7711
7712     /* if right is bit then exchange them */
7713     if (AOP_TYPE(right) == AOP_CRY &&
7714         AOP_TYPE(left) != AOP_CRY){
7715         operand *tmp = right ;
7716         right = left;
7717         left = tmp;
7718     }
7719
7720     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7721
7722     if(AOP_TYPE(right) == AOP_LIT)
7723         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7724
7725     size = AOP_SIZE(result);
7726
7727     // if(bit | yy)
7728     // xx = bit | yy;
7729     if (AOP_TYPE(left) == AOP_CRY){
7730         if(AOP_TYPE(right) == AOP_LIT){
7731             // c = bit & literal;
7732             if(lit){
7733                 // lit != 0 => result = 1
7734                 if(AOP_TYPE(result) == AOP_CRY){
7735                   if(size)
7736                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7737                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7738                   //     AOP(result)->aopu.aop_dir,
7739                   //     AOP(result)->aopu.aop_dir);
7740                     else if(ifx)
7741                         continueIfTrue(ifx);
7742                     goto release;
7743                 }
7744             } else {
7745                 // lit == 0 => result = left
7746                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7747                     goto release;
7748                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7749             }
7750         } else {
7751             if (AOP_TYPE(right) == AOP_CRY){
7752               if(pic16_sameRegs(AOP(result),AOP(left))){
7753                 // c = bit | bit;
7754                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7755                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7756                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7757
7758                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7759                          AOP(result)->aopu.aop_dir,
7760                          AOP(result)->aopu.aop_dir);
7761                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7762                          AOP(right)->aopu.aop_dir,
7763                          AOP(right)->aopu.aop_dir);
7764                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7765                          AOP(result)->aopu.aop_dir,
7766                          AOP(result)->aopu.aop_dir);
7767               } else {
7768                 if( AOP_TYPE(result) == AOP_ACC) {
7769                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7770                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7771                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7772                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7773
7774                 } else {
7775
7776                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7777                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7778                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7779                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7780
7781                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7782                                  AOP(result)->aopu.aop_dir,
7783                                  AOP(result)->aopu.aop_dir);
7784                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7785                                  AOP(right)->aopu.aop_dir,
7786                                  AOP(right)->aopu.aop_dir);
7787                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7788                                  AOP(left)->aopu.aop_dir,
7789                                  AOP(left)->aopu.aop_dir);
7790                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7791                                  AOP(result)->aopu.aop_dir,
7792                                  AOP(result)->aopu.aop_dir);
7793                 }
7794               }
7795             } else {
7796                 // c = bit | val;
7797                 symbol *tlbl = newiTempLabel(NULL);
7798                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7799
7800
7801                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7802                 if( AOP_TYPE(right) == AOP_ACC) {
7803                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7804                   emitSKPNZ;
7805                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7806                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7807                 }
7808
7809
7810
7811                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7812                     pic16_emitcode(";XXX setb","c");
7813                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7814                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7815                 pic16_toBoolean(right);
7816                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7817                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7818                     jmpTrueOrFalse(ifx, tlbl);
7819                     goto release;
7820                 } else {
7821                     CLRC;
7822                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7823                 }
7824             }
7825         }
7826         // bit = c
7827         // val = c
7828         if(size)
7829             pic16_outBitC(result);
7830         // if(bit | ...)
7831         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7832             genIfxJump(ifx, "c");           
7833         goto release ;
7834     }
7835
7836     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7837     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7838     if((AOP_TYPE(right) == AOP_LIT) &&
7839        (AOP_TYPE(result) == AOP_CRY) &&
7840        (AOP_TYPE(left) != AOP_CRY)){
7841         if(lit){
7842           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7843             // result = 1
7844             if(size)
7845                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7846             else 
7847                 continueIfTrue(ifx);
7848             goto release;
7849         } else {
7850           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7851             // lit = 0, result = boolean(left)
7852             if(size)
7853                 pic16_emitcode(";XXX setb","c");
7854             pic16_toBoolean(right);
7855             if(size){
7856                 symbol *tlbl = newiTempLabel(NULL);
7857                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7858                 CLRC;
7859                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7860             } else {
7861                 genIfxJump (ifx,"a");
7862                 goto release;
7863             }
7864         }
7865         pic16_outBitC(result);
7866         goto release ;
7867     }
7868
7869     /* if left is same as result */
7870     if(pic16_sameRegs(AOP(result),AOP(left))){
7871       int know_W = -1;
7872       for(;size--; offset++,lit>>=8) {
7873         if(AOP_TYPE(right) == AOP_LIT){
7874           if((lit & 0xff) == 0)
7875             /*  or'ing with 0 has no effect */
7876             continue;
7877           else {
7878             int p = pic16_my_powof2(lit & 0xff);
7879             if(p>=0) {
7880               /* only one bit is set in the literal, so use a bsf instruction */
7881               pic16_emitpcode(POC_BSF,
7882                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7883             } else {
7884               if(know_W != (lit & 0xff))
7885                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7886               know_W = lit & 0xff;
7887               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7888             }
7889                     
7890           }
7891         } else {
7892           if (AOP_TYPE(left) == AOP_ACC) {
7893             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7894             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7895           } else {                  
7896             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7897             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7898
7899             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7900             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7901
7902           }
7903         }
7904       }
7905     } else {
7906         // left & result in different registers
7907         if(AOP_TYPE(result) == AOP_CRY){
7908             // result = bit
7909             // if(size), result in bit
7910             // if(!size && ifx), conditional oper: if(left | right)
7911             symbol *tlbl = newiTempLabel(NULL);
7912             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7913             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7914
7915
7916             if(size)
7917                 pic16_emitcode(";XXX setb","c");
7918             while(sizer--){
7919                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7920                 pic16_emitcode(";XXX orl","a,%s",
7921                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7922                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7923                 offset++;
7924             }
7925             if(size){
7926                 CLRC;
7927                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7928                 pic16_outBitC(result);
7929             } else if(ifx)
7930                 jmpTrueOrFalse(ifx, tlbl);
7931         } else for(;(size--);offset++){
7932           // normal case
7933           // result = left & right
7934           if(AOP_TYPE(right) == AOP_LIT){
7935             int t = (lit >> (offset*8)) & 0x0FFL;
7936             switch(t) { 
7937             case 0x00:
7938               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7939               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7940
7941               pic16_emitcode("movf","%s,w",
7942                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7943               pic16_emitcode("movwf","%s",
7944                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7945               break;
7946             default:
7947               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7948               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7949               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7950
7951               pic16_emitcode("movlw","0x%x",t);
7952               pic16_emitcode("iorwf","%s,w",
7953                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7954               pic16_emitcode("movwf","%s",
7955                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7956               
7957             }
7958             continue;
7959           }
7960
7961           // faster than result <- left, anl result,right
7962           // and better if result is SFR
7963           if (AOP_TYPE(left) == AOP_ACC) {
7964             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7965             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7966           } else {
7967             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7968             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7969
7970             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7971             pic16_emitcode("iorwf","%s,w",
7972                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7973           }
7974           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7975           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7976         }
7977     }
7978
7979 release :
7980     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7981     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7982     pic16_freeAsmop(result,NULL,ic,TRUE);     
7983 }
7984
7985 /*-----------------------------------------------------------------*/
7986 /* genXor - code for xclusive or                                   */
7987 /*-----------------------------------------------------------------*/
7988 static void genXor (iCode *ic, iCode *ifx)
7989 {
7990   operand *left, *right, *result;
7991   int size, offset=0;
7992   unsigned long lit = 0L;
7993
7994   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7995
7996   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7997   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7998   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7999
8000   /* if left is a literal & right is not ||
8001      if left needs acc & right does not */
8002   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8003       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8004     operand *tmp = right ;
8005     right = left;
8006     left = tmp;
8007   }
8008
8009   /* if result = right then exchange them */
8010   if(pic16_sameRegs(AOP(result),AOP(right))){
8011     operand *tmp = right ;
8012     right = left;
8013     left = tmp;
8014   }
8015
8016   /* if right is bit then exchange them */
8017   if (AOP_TYPE(right) == AOP_CRY &&
8018       AOP_TYPE(left) != AOP_CRY){
8019     operand *tmp = right ;
8020     right = left;
8021     left = tmp;
8022   }
8023   if(AOP_TYPE(right) == AOP_LIT)
8024     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8025
8026   size = AOP_SIZE(result);
8027
8028   // if(bit ^ yy)
8029   // xx = bit ^ yy;
8030   if (AOP_TYPE(left) == AOP_CRY){
8031     if(AOP_TYPE(right) == AOP_LIT){
8032       // c = bit & literal;
8033       if(lit>>1){
8034         // lit>>1  != 0 => result = 1
8035         if(AOP_TYPE(result) == AOP_CRY){
8036           if(size)
8037             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8038             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8039           else if(ifx)
8040             continueIfTrue(ifx);
8041           goto release;
8042         }
8043         pic16_emitcode("setb","c");
8044       } else{
8045         // lit == (0 or 1)
8046         if(lit == 0){
8047           // lit == 0, result = left
8048           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8049             goto release;
8050           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8051         } else{
8052           // lit == 1, result = not(left)
8053           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8054             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8055             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8056             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8057             goto release;
8058           } else {
8059             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8060             pic16_emitcode("cpl","c");
8061           }
8062         }
8063       }
8064
8065     } else {
8066       // right != literal
8067       symbol *tlbl = newiTempLabel(NULL);
8068       if (AOP_TYPE(right) == AOP_CRY){
8069         // c = bit ^ bit;
8070         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8071       }
8072       else{
8073         int sizer = AOP_SIZE(right);
8074         // c = bit ^ val
8075         // if val>>1 != 0, result = 1
8076         pic16_emitcode("setb","c");
8077         while(sizer){
8078           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8079           if(sizer == 1)
8080             // test the msb of the lsb
8081             pic16_emitcode("anl","a,#0xfe");
8082           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8083           sizer--;
8084         }
8085         // val = (0,1)
8086         pic16_emitcode("rrc","a");
8087       }
8088       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8089       pic16_emitcode("cpl","c");
8090       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8091     }
8092     // bit = c
8093     // val = c
8094     if(size)
8095       pic16_outBitC(result);
8096     // if(bit | ...)
8097     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8098       genIfxJump(ifx, "c");           
8099     goto release ;
8100   }
8101
8102   if(pic16_sameRegs(AOP(result),AOP(left))){
8103     /* if left is same as result */
8104     for(;size--; offset++) {
8105       if(AOP_TYPE(right) == AOP_LIT){
8106         int t  = (lit >> (offset*8)) & 0x0FFL;
8107         if(t == 0x00L)
8108           continue;
8109         else
8110           if (IS_AOP_PREG(left)) {
8111             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8112             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8113             pic16_aopPut(AOP(result),"a",offset);
8114           } else {
8115             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8116             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8117             pic16_emitcode("xrl","%s,%s",
8118                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8119                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8120           }
8121       } else {
8122         if (AOP_TYPE(left) == AOP_ACC)
8123           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8124         else {
8125           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8126           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8127 /*
8128           if (IS_AOP_PREG(left)) {
8129             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8130             pic16_aopPut(AOP(result),"a",offset);
8131           } else
8132             pic16_emitcode("xrl","%s,a",
8133                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8134 */
8135         }
8136       }
8137     }
8138   } else {
8139     // left & result in different registers
8140     if(AOP_TYPE(result) == AOP_CRY){
8141       // result = bit
8142       // if(size), result in bit
8143       // if(!size && ifx), conditional oper: if(left ^ right)
8144       symbol *tlbl = newiTempLabel(NULL);
8145       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8146       if(size)
8147         pic16_emitcode("setb","c");
8148       while(sizer--){
8149         if((AOP_TYPE(right) == AOP_LIT) &&
8150            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8151           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8152         } else {
8153           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8154           pic16_emitcode("xrl","a,%s",
8155                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8156         }
8157         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8158         offset++;
8159       }
8160       if(size){
8161         CLRC;
8162         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8163         pic16_outBitC(result);
8164       } else if(ifx)
8165         jmpTrueOrFalse(ifx, tlbl);
8166     } else for(;(size--);offset++){
8167       // normal case
8168       // result = left & right
8169       if(AOP_TYPE(right) == AOP_LIT){
8170         int t = (lit >> (offset*8)) & 0x0FFL;
8171         switch(t) { 
8172         case 0x00:
8173           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8174           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8175           pic16_emitcode("movf","%s,w",
8176                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8177           pic16_emitcode("movwf","%s",
8178                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8179           break;
8180         case 0xff:
8181           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8182           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8183           pic16_emitcode("comf","%s,w",
8184                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8185           pic16_emitcode("movwf","%s",
8186                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8187           break;
8188         default:
8189           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8190           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8191           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8192           pic16_emitcode("movlw","0x%x",t);
8193           pic16_emitcode("xorwf","%s,w",
8194                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8195           pic16_emitcode("movwf","%s",
8196                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8197
8198         }
8199         continue;
8200       }
8201
8202       // faster than result <- left, anl result,right
8203       // and better if result is SFR
8204       if (AOP_TYPE(left) == AOP_ACC) {
8205         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8206         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8207       } else {
8208         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8209         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8210         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8211         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8212       }
8213       if ( AOP_TYPE(result) != AOP_ACC){
8214         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8215         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8216       }
8217     }
8218   }
8219
8220   release :
8221     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8222   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8223   pic16_freeAsmop(result,NULL,ic,TRUE);     
8224 }
8225
8226 /*-----------------------------------------------------------------*/
8227 /* genInline - write the inline code out                           */
8228 /*-----------------------------------------------------------------*/
8229 static void genInline (iCode *ic)
8230 {
8231   char *buffer, *bp, *bp1;
8232     
8233         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8234
8235         _G.inLine += (!options.asmpeep);
8236
8237         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8238         strcpy(buffer,IC_INLINE(ic));
8239         
8240         while((bp1=strstr(bp, "\\n"))) {
8241           *bp1++ = '\n';
8242           *bp1++ = ' ';
8243           bp = bp1;
8244         }
8245         bp = bp1 = buffer;
8246
8247 #if 0
8248   /* This is an experimental code for #pragma inline
8249      and is temporarily disabled for 2.5.0 release */
8250         if(asmInlineMap)
8251         {
8252           symbol *sym;
8253           char *s;
8254           char *cbuf;
8255           int cblen;
8256
8257             cbuf = Safe_strdup(buffer);
8258             cblen = strlen(buffer)+1;
8259             memset(cbuf, 0, cblen);
8260
8261             bp = buffer;
8262             bp1 = cbuf;
8263             while(*bp) {
8264               if(*bp != '%')*bp1++ = *bp++;
8265               else {
8266                 int i;
8267
8268                   bp++;
8269                   i = *bp - '0';
8270                   if(i>elementsInSet(asmInlineMap))break;
8271                   
8272                   bp++;
8273                   s = indexSet(asmInlineMap, i);
8274                   DEBUGpc("searching symbol s = `%s'", s);
8275                   sym = findSym(SymbolTab, NULL, s);
8276
8277                   if(sym->reqv) {
8278                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8279                   } else {
8280                     strcat(bp1, sym->rname);
8281                   }
8282                   
8283                   while(*bp1)bp1++;
8284               }
8285               
8286               if(strlen(bp1) > cblen - 16) {
8287                 int i = strlen(cbuf);
8288                 cblen += 50;
8289                 cbuf = realloc(cbuf, cblen);
8290                 memset(cbuf+i, 0, 50);
8291                 bp1 = cbuf + i;
8292               }
8293             }
8294             
8295             free(buffer);
8296             buffer = Safe_strdup( cbuf );
8297             free(cbuf);
8298             
8299             bp = bp1 = buffer;
8300         }
8301 #endif  /* 0 */
8302
8303         /* emit each line as a code */
8304         while (*bp) {
8305                 if (*bp == '\n') {
8306                         *bp++ = '\0';
8307
8308                         if(*bp1)
8309                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8310                         bp1 = bp;
8311                 } else {
8312                         if (*bp == ':') {
8313                                 bp++;
8314                                 *bp = '\0';
8315                                 bp++;
8316
8317                                 /* print label, use this special format with NULL directive
8318                                  * to denote that the argument should not be indented with tab */
8319                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8320                                 bp1 = bp;
8321                         } else
8322                                 bp++;
8323                 }
8324         }
8325
8326         if ((bp1 != bp) && *bp1)
8327                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8328
8329
8330     Safe_free(buffer);
8331
8332     _G.inLine -= (!options.asmpeep);
8333 }
8334
8335 /*-----------------------------------------------------------------*/
8336 /* genRRC - rotate right with carry                                */
8337 /*-----------------------------------------------------------------*/
8338 static void genRRC (iCode *ic)
8339 {
8340   operand *left , *result ;
8341   int size, offset = 0, same;
8342
8343   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8344
8345   /* rotate right with carry */
8346   left = IC_LEFT(ic);
8347   result=IC_RESULT(ic);
8348   pic16_aopOp (left,ic,FALSE);
8349   pic16_aopOp (result,ic,TRUE);
8350
8351   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8352
8353   same = pic16_sameRegs(AOP(result),AOP(left));
8354
8355   size = AOP_SIZE(result);    
8356
8357   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8358
8359   /* get the lsb and put it into the carry */
8360   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8361
8362   offset = 0 ;
8363
8364   while(size--) {
8365
8366     if(same) {
8367       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8368     } else {
8369       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8370       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8371     }
8372
8373     offset++;
8374   }
8375
8376   pic16_freeAsmop(left,NULL,ic,TRUE);
8377   pic16_freeAsmop(result,NULL,ic,TRUE);
8378 }
8379
8380 /*-----------------------------------------------------------------*/
8381 /* genRLC - generate code for rotate left with carry               */
8382 /*-----------------------------------------------------------------*/
8383 static void genRLC (iCode *ic)
8384 {    
8385   operand *left , *result ;
8386   int size, offset = 0;
8387   int same;
8388
8389   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8390   /* rotate right with carry */
8391   left = IC_LEFT(ic);
8392   result=IC_RESULT(ic);
8393   pic16_aopOp (left,ic,FALSE);
8394   pic16_aopOp (result,ic,TRUE);
8395
8396   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8397
8398   same = pic16_sameRegs(AOP(result),AOP(left));
8399
8400   /* move it to the result */
8401   size = AOP_SIZE(result);    
8402
8403   /* get the msb and put it into the carry */
8404   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8405
8406   offset = 0 ;
8407
8408   while(size--) {
8409
8410     if(same) {
8411       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8412     } else {
8413       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8414       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8415     }
8416
8417     offset++;
8418   }
8419
8420
8421   pic16_freeAsmop(left,NULL,ic,TRUE);
8422   pic16_freeAsmop(result,NULL,ic,TRUE);
8423 }
8424
8425
8426 /* gpasm can get the highest order bit with HIGH/UPPER
8427  * so the following probably is not needed -- VR */
8428  
8429 /*-----------------------------------------------------------------*/
8430 /* genGetHbit - generates code get highest order bit               */
8431 /*-----------------------------------------------------------------*/
8432 static void genGetHbit (iCode *ic)
8433 {
8434     operand *left, *result;
8435     left = IC_LEFT(ic);
8436     result=IC_RESULT(ic);
8437     pic16_aopOp (left,ic,FALSE);
8438     pic16_aopOp (result,ic,FALSE);
8439
8440     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8441     /* get the highest order byte into a */
8442     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8443     if(AOP_TYPE(result) == AOP_CRY){
8444         pic16_emitcode("rlc","a");
8445         pic16_outBitC(result);
8446     }
8447     else{
8448         pic16_emitcode("rl","a");
8449         pic16_emitcode("anl","a,#0x01");
8450         pic16_outAcc(result);
8451     }
8452
8453
8454     pic16_freeAsmop(left,NULL,ic,TRUE);
8455     pic16_freeAsmop(result,NULL,ic,TRUE);
8456 }
8457
8458 #if 0
8459 /*-----------------------------------------------------------------*/
8460 /* AccRol - rotate left accumulator by known count                 */
8461 /*-----------------------------------------------------------------*/
8462 static void AccRol (int shCount)
8463 {
8464     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8465     shCount &= 0x0007;              // shCount : 0..7
8466     switch(shCount){
8467         case 0 :
8468             break;
8469         case 1 :
8470             pic16_emitcode("rl","a");
8471             break;
8472         case 2 :
8473             pic16_emitcode("rl","a");
8474             pic16_emitcode("rl","a");
8475             break;
8476         case 3 :
8477             pic16_emitcode("swap","a");
8478             pic16_emitcode("rr","a");
8479             break;
8480         case 4 :
8481             pic16_emitcode("swap","a");
8482             break;
8483         case 5 :
8484             pic16_emitcode("swap","a");
8485             pic16_emitcode("rl","a");
8486             break;
8487         case 6 :
8488             pic16_emitcode("rr","a");
8489             pic16_emitcode("rr","a");
8490             break;
8491         case 7 :
8492             pic16_emitcode("rr","a");
8493             break;
8494     }
8495 }
8496 #endif
8497
8498 /*-----------------------------------------------------------------*/
8499 /* AccLsh - left shift accumulator by known count                  */
8500 /*-----------------------------------------------------------------*/
8501 static void AccLsh (int shCount)
8502 {
8503         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8504         switch(shCount){
8505                 case 0 :
8506                         return;
8507                         break;
8508                 case 1 :
8509                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8510                         break;
8511                 case 2 :
8512                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8513                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8514                         break;
8515                 case 3 :
8516                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8517                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8518                         break;
8519                 case 4 :
8520                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8521                         break;
8522                 case 5 :
8523                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8524                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8525                         break;
8526                 case 6 :
8527                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8528                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8529                         break;
8530                 case 7 :
8531                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8532                         break;
8533         }
8534
8535         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8536 }
8537
8538 /*-----------------------------------------------------------------*/
8539 /* AccRsh - right shift accumulator by known count                 */
8540 /*-----------------------------------------------------------------*/
8541 static void AccRsh (int shCount, int andmask)
8542 {
8543         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8544         switch(shCount){
8545                 case 0 :
8546                         return; break;
8547                 case 1 :
8548                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8549                         break;
8550                 case 2 :
8551                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8552                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8553                         break;
8554                 case 3 :
8555                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8556                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8557                         break;
8558                 case 4 :
8559                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8560                         break;
8561                 case 5 :
8562                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8563                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8564                         break;
8565                 case 6 :
8566                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8567                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8568                         break;
8569                 case 7 :
8570                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8571                         break;
8572         }
8573         
8574         if(andmask)
8575                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8576         else
8577                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8578 }
8579
8580 #if 0
8581 /*-----------------------------------------------------------------*/
8582 /* AccSRsh - signed right shift accumulator by known count                 */
8583 /*-----------------------------------------------------------------*/
8584 static void AccSRsh (int shCount)
8585 {
8586     symbol *tlbl ;
8587     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8588     if(shCount != 0){
8589         if(shCount == 1){
8590             pic16_emitcode("mov","c,acc.7");
8591             pic16_emitcode("rrc","a");
8592         } else if(shCount == 2){
8593             pic16_emitcode("mov","c,acc.7");
8594             pic16_emitcode("rrc","a");
8595             pic16_emitcode("mov","c,acc.7");
8596             pic16_emitcode("rrc","a");
8597         } else {
8598             tlbl = newiTempLabel(NULL);
8599             /* rotate right accumulator */
8600             AccRol(8 - shCount);
8601             /* and kill the higher order bits */
8602             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8603             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8604             pic16_emitcode("orl","a,#0x%02x",
8605                      (unsigned char)~SRMask[shCount]);
8606             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8607         }
8608     }
8609 }
8610 #endif
8611
8612 /*-----------------------------------------------------------------*/
8613 /* shiftR1Left2Result - shift right one byte from left to result   */
8614 /*-----------------------------------------------------------------*/
8615 static void shiftR1Left2ResultSigned (operand *left, int offl,
8616                                 operand *result, int offr,
8617                                 int shCount)
8618 {
8619   int same;
8620
8621   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8622
8623   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8624
8625   switch(shCount) {
8626   case 1:
8627     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8628     if(same) 
8629       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8630     else {
8631       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8632       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8633     }
8634
8635     break;
8636   case 2:
8637
8638     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8639     if(same) 
8640       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8641     else {
8642       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8643       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8644     }
8645     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8646     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8647
8648     break;
8649
8650   case 3:
8651     if(same)
8652       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8653     else {
8654       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8655       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8656     }
8657
8658     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8659     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8660     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8661
8662     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8663     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8664
8665     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8666     break;
8667
8668   case 4:
8669     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8670     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8671     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8672     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8673     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8674     break;
8675   case 5:
8676     if(same) {
8677       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8678     } else {
8679       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8680       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8681     }
8682     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8683     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8684     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8685     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8686     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8687     break;
8688
8689   case 6:
8690     if(same) {
8691       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8692       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8693       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8694       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8695       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8696       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8697     } else {
8698       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8699       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8700       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8701       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8702       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8703     }
8704     break;
8705
8706   case 7:
8707     if(same) {
8708       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8709       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8710       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8711       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8712     } else {
8713       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8714       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8715       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8716     }
8717
8718   default:
8719     break;
8720   }
8721 }
8722
8723 /*-----------------------------------------------------------------*/
8724 /* shiftR1Left2Result - shift right one byte from left to result   */
8725 /*-----------------------------------------------------------------*/
8726 static void shiftR1Left2Result (operand *left, int offl,
8727                                 operand *result, int offr,
8728                                 int shCount, int sign)
8729 {
8730   int same;
8731
8732   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8733
8734   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8735
8736   /* Copy the msb into the carry if signed. */
8737   if(sign) {
8738     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8739     return;
8740   }
8741
8742
8743
8744   switch(shCount) {
8745   case 1:
8746     emitCLRC;
8747     if(same) 
8748       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8749     else {
8750       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8751       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8752     }
8753     break;
8754   case 2:
8755     emitCLRC;
8756     if(same) {
8757       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8758     } else {
8759       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8760       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8761     }
8762     emitCLRC;
8763     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8764
8765     break;
8766   case 3:
8767     if(same)
8768       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8769     else {
8770       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8771       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8772     }
8773
8774     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8775     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8776     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8777     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8778     break;
8779       
8780   case 4:
8781     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8782     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8783     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8784     break;
8785
8786   case 5:
8787     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8788     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8789     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8790     //emitCLRC;
8791     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8792
8793     break;
8794   case 6:
8795
8796     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8797     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8798     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8799     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8800     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8801     break;
8802
8803   case 7:
8804
8805     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8806     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8807     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8808
8809     break;
8810
8811   default:
8812     break;
8813   }
8814 }
8815
8816 /*-----------------------------------------------------------------*/
8817 /* shiftL1Left2Result - shift left one byte from left to result    */
8818 /*-----------------------------------------------------------------*/
8819 static void shiftL1Left2Result (operand *left, int offl,
8820                                 operand *result, int offr, int shCount)
8821 {
8822   int same;
8823
8824   //    char *l;
8825   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8826
8827   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8828   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8829     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8830     //    MOVA(l);
8831     /* shift left accumulator */
8832     //AccLsh(shCount); // don't comment out just yet...
8833   //    pic16_aopPut(AOP(result),"a",offr);
8834
8835   switch(shCount) {
8836   case 1:
8837     /* Shift left 1 bit position */
8838     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8839     if(same) {
8840       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8841     } else {
8842       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8843       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8844     }
8845     break;
8846   case 2:
8847     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8848     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8849     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8850     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8851     break;
8852   case 3:
8853     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8854     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8855     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8856     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8857     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8858     break;
8859   case 4:
8860     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8861     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8862     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8863     break;
8864   case 5:
8865     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8866     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8867     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8868     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8869     break;
8870   case 6:
8871     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8872     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8873     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8874     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8875     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8876     break;
8877   case 7:
8878     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8879     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8880     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8881     break;
8882
8883   default:
8884     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8885   }
8886
8887 }
8888
8889 /*-----------------------------------------------------------------*/
8890 /* movLeft2Result - move byte from left to result                  */
8891 /*-----------------------------------------------------------------*/
8892 static void movLeft2Result (operand *left, int offl,
8893                             operand *result, int offr)
8894 {
8895   char *l;
8896   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8897   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8898     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8899
8900     if (*l == '@' && (IS_AOP_PREG(result))) {
8901       pic16_emitcode("mov","a,%s",l);
8902       pic16_aopPut(AOP(result),"a",offr);
8903     } else {
8904       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8905       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8906     }
8907   }
8908 }
8909
8910 /*-----------------------------------------------------------------*/
8911 /* shiftL2Left2Result - shift left two bytes from left to result   */
8912 /*-----------------------------------------------------------------*/
8913 static void shiftL2Left2Result (operand *left, int offl,
8914                                 operand *result, int offr, int shCount)
8915 {
8916   int same = pic16_sameRegs(AOP(result), AOP(left));
8917   int i;
8918
8919   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8920
8921   if (same && (offl != offr)) { // shift bytes
8922     if (offr > offl) {
8923        for(i=1;i>-1;i--) {
8924          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8925          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8926        }
8927     } else { // just treat as different later on
8928                 same = 0;
8929     }
8930   }
8931
8932   if(same) {
8933     switch(shCount) {
8934     case 0:
8935       break;
8936     case 1:
8937     case 2:
8938     case 3:
8939
8940       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8941       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8942       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8943
8944       while(--shCount) {
8945                 emitCLRC;
8946                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8947                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8948       }
8949
8950       break;
8951     case 4:
8952     case 5:
8953       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8954       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8955       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8956       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8957       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8958       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8959       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8960       if(shCount >=5) {
8961                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8962                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8963       }
8964       break;
8965     case 6:
8966       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8967       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8968       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8969       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8970       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8971       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8972       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8973       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8974       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8975       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8976       break;
8977     case 7:
8978       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8979       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8980       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8981       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8982       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8983     }
8984
8985   } else {
8986     switch(shCount) {
8987     case 0:
8988       break;
8989     case 1:
8990     case 2:
8991     case 3:
8992       /* note, use a mov/add for the shift since the mov has a
8993          chance of getting optimized out */
8994       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8995       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8996       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8997       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8998       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8999
9000       while(--shCount) {
9001                 emitCLRC;
9002                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9003                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9004       }
9005       break;
9006
9007     case 4:
9008     case 5:
9009       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9010       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9011       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9012       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9013       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9014       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9015       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9016       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9017
9018
9019       if(shCount == 5) {
9020                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9021                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9022       }
9023       break;
9024     case 6:
9025       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9026       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9027       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9028       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9029
9030       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9031       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9032       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9033       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9034       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9035       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9036       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9037       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9038       break;
9039     case 7:
9040       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9041       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9042       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9043       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9044       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9045     }
9046   }
9047
9048 }
9049 /*-----------------------------------------------------------------*/
9050 /* shiftR2Left2Result - shift right two bytes from left to result  */
9051 /*-----------------------------------------------------------------*/
9052 static void shiftR2Left2Result (operand *left, int offl,
9053                                 operand *result, int offr,
9054                                 int shCount, int sign)
9055 {
9056   int same = pic16_sameRegs(AOP(result), AOP(left));
9057   int i;
9058   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9059
9060   if (same && (offl != offr)) { // shift right bytes
9061     if (offr < offl) {
9062        for(i=0;i<2;i++) {
9063          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9064          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9065        }
9066     } else { // just treat as different later on
9067                 same = 0;
9068     }
9069   }
9070
9071   switch(shCount) {
9072   case 0:
9073     break;
9074   case 1:
9075   case 2:
9076   case 3:
9077     if(sign)
9078       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9079     else
9080       emitCLRC;
9081
9082     if(same) {
9083       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9084       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9085     } else {
9086       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9087       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9088       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9089       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9090     }
9091
9092     while(--shCount) {
9093       if(sign)
9094                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9095       else
9096                 emitCLRC;
9097       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9098       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9099     }
9100     break;
9101   case 4:
9102   case 5:
9103     if(same) {
9104
9105       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9106       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9107       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9108
9109       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9110       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9111       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9112       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9113     } else {
9114       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9115       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9116       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9117
9118       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9119       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9120       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9121       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9122       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9123     }
9124
9125     if(shCount >=5) {
9126       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9127       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9128     }
9129
9130     if(sign) {
9131       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9132       pic16_emitpcode(POC_BTFSC, 
9133                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9134       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9135     }
9136
9137     break;
9138
9139   case 6:
9140     if(same) {
9141
9142       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9143       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9144
9145       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9146       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9147       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9148       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9149       if(sign) {
9150         pic16_emitpcode(POC_BTFSC, 
9151                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9152         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9153       }
9154       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9155       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9156       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9157       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9158     } else {
9159       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9160       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9161       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9162       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9163       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9164       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9165       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9166       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9167       if(sign) {
9168         pic16_emitpcode(POC_BTFSC, 
9169                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9170         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9171       }
9172       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9173       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9174
9175         
9176     }
9177
9178     break;
9179   case 7:
9180     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9181     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9182     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9183     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9184     if(sign) {
9185       emitSKPNC;
9186       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9187     } else 
9188       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9189   }
9190 }
9191
9192
9193 /*-----------------------------------------------------------------*/
9194 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9195 /*-----------------------------------------------------------------*/
9196 static void shiftLLeftOrResult (operand *left, int offl,
9197                                 operand *result, int offr, int shCount)
9198 {
9199     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9200
9201     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9202     /* shift left accumulator */
9203     AccLsh(shCount);
9204     /* or with result */
9205     /* back to result */
9206     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9207 }
9208
9209 /*-----------------------------------------------------------------*/
9210 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9211 /*-----------------------------------------------------------------*/
9212 static void shiftRLeftOrResult (operand *left, int offl,
9213                                 operand *result, int offr, int shCount)
9214 {
9215     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9216     
9217     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9218     /* shift right accumulator */
9219     AccRsh(shCount, 1);
9220     /* or with result */
9221     /* back to result */
9222     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9223 }
9224
9225 /*-----------------------------------------------------------------*/
9226 /* genlshOne - left shift a one byte quantity by known count       */
9227 /*-----------------------------------------------------------------*/
9228 static void genlshOne (operand *result, operand *left, int shCount)
9229 {       
9230     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9231     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9232 }
9233
9234 /*-----------------------------------------------------------------*/
9235 /* genlshTwo - left shift two bytes by known amount != 0           */
9236 /*-----------------------------------------------------------------*/
9237 static void genlshTwo (operand *result,operand *left, int shCount)
9238 {
9239     int size;
9240     
9241     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9242     size = pic16_getDataSize(result);
9243
9244     /* if shCount >= 8 */
9245     if (shCount >= 8) {
9246         shCount -= 8 ;
9247
9248         if (size > 1){
9249             if (shCount)
9250                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9251             else 
9252                 movLeft2Result(left, LSB, result, MSB16);
9253         }
9254         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9255     }
9256
9257     /*  1 <= shCount <= 7 */
9258     else {  
9259         if(size == 1)
9260             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9261         else 
9262             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9263     }
9264 }
9265
9266 /*-----------------------------------------------------------------*/
9267 /* shiftLLong - shift left one long from left to result            */
9268 /* offr = LSB or MSB16                                             */
9269 /*-----------------------------------------------------------------*/
9270 static void shiftLLong (operand *left, operand *result, int offr )
9271 {
9272     int size = AOP_SIZE(result);
9273     int same = pic16_sameRegs(AOP(left),AOP(result));
9274         int i;
9275
9276     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9277
9278         if (same && (offr == MSB16)) { //shift one byte
9279                 for(i=size-1;i>=MSB16;i--) {
9280                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9281                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9282                 }
9283         } else {
9284                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9285         }
9286         
9287     if (size > LSB+offr ){
9288                 if (same) {
9289                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9290                 } else {
9291                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9292                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9293                 }
9294          }
9295
9296     if(size > MSB16+offr){
9297                 if (same) {
9298                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9299                 } else {
9300                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9301                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9302                 }
9303     }
9304
9305     if(size > MSB24+offr){
9306                 if (same) {
9307                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9308                 } else {
9309                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9310                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9311                 }
9312     }
9313
9314     if(size > MSB32+offr){
9315                 if (same) {
9316                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9317                 } else {
9318                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9319                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9320                 }
9321     }
9322     if(offr != LSB)
9323                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9324
9325 }
9326
9327 /*-----------------------------------------------------------------*/
9328 /* genlshFour - shift four byte by a known amount != 0             */
9329 /*-----------------------------------------------------------------*/
9330 static void genlshFour (operand *result, operand *left, int shCount)
9331 {
9332     int size;
9333
9334     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9335     size = AOP_SIZE(result);
9336
9337     /* if shifting more that 3 bytes */
9338     if (shCount >= 24 ) {
9339         shCount -= 24;
9340         if (shCount)
9341             /* lowest order of left goes to the highest
9342             order of the destination */
9343             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9344         else
9345             movLeft2Result(left, LSB, result, MSB32);
9346
9347                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9348                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9349                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9350
9351         return;
9352     }
9353
9354     /* more than two bytes */
9355     else if ( shCount >= 16 ) {
9356         /* lower order two bytes goes to higher order two bytes */
9357         shCount -= 16;
9358         /* if some more remaining */
9359         if (shCount)
9360             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9361         else {
9362             movLeft2Result(left, MSB16, result, MSB32);
9363             movLeft2Result(left, LSB, result, MSB24);
9364         }
9365                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9366                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9367         return;
9368     }    
9369
9370     /* if more than 1 byte */
9371     else if ( shCount >= 8 ) {
9372         /* lower order three bytes goes to higher order  three bytes */
9373         shCount -= 8;
9374         if(size == 2){
9375             if(shCount)
9376                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9377             else
9378                 movLeft2Result(left, LSB, result, MSB16);
9379         }
9380         else{   /* size = 4 */
9381             if(shCount == 0){
9382                 movLeft2Result(left, MSB24, result, MSB32);
9383                 movLeft2Result(left, MSB16, result, MSB24);
9384                 movLeft2Result(left, LSB, result, MSB16);
9385                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9386             }
9387             else if(shCount == 1)
9388                 shiftLLong(left, result, MSB16);
9389             else{
9390                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9391                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9392                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9393                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9394             }
9395         }
9396     }
9397
9398     /* 1 <= shCount <= 7 */
9399     else if(shCount <= 3)
9400     { 
9401         shiftLLong(left, result, LSB);
9402         while(--shCount >= 1)
9403             shiftLLong(result, result, LSB);
9404     }
9405     /* 3 <= shCount <= 7, optimize */
9406     else{
9407         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9408         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9409         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9410     }
9411 }
9412
9413 /*-----------------------------------------------------------------*/
9414 /* genLeftShiftLiteral - left shifting by known count              */
9415 /*-----------------------------------------------------------------*/
9416 void pic16_genLeftShiftLiteral (operand *left,
9417                                  operand *right,
9418                                  operand *result,
9419                                  iCode *ic)
9420 {    
9421     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9422     int size;
9423
9424     FENTRY;
9425     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9426     pic16_freeAsmop(right,NULL,ic,TRUE);
9427
9428     pic16_aopOp(left,ic,FALSE);
9429     pic16_aopOp(result,ic,TRUE);
9430
9431     size = getSize(operandType(result));
9432
9433 #if VIEW_SIZE
9434     pic16_emitcode("; shift left ","result %d, left %d",size,
9435              AOP_SIZE(left));
9436 #endif
9437
9438     /* I suppose that the left size >= result size */
9439     if(shCount == 0){
9440         while(size--){
9441             movLeft2Result(left, size, result, size);
9442         }
9443     }
9444
9445     else if(shCount >= (size * 8))
9446         while(size--)
9447             pic16_aopPut(AOP(result),zero,size);
9448     else{
9449         switch (size) {
9450             case 1:
9451                 genlshOne (result,left,shCount);
9452                 break;
9453
9454             case 2:
9455             case 3:
9456                 genlshTwo (result,left,shCount);
9457                 break;
9458
9459             case 4:
9460                 genlshFour (result,left,shCount);
9461                 break;
9462         }
9463     }
9464     pic16_freeAsmop(left,NULL,ic,TRUE);
9465     pic16_freeAsmop(result,NULL,ic,TRUE);
9466 }
9467
9468 /*-----------------------------------------------------------------*
9469  * genMultiAsm - repeat assembly instruction for size of register.
9470  * if endian == 1, then the high byte (i.e base address + size of 
9471  * register) is used first else the low byte is used first;
9472  *-----------------------------------------------------------------*/
9473 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9474 {
9475
9476   int offset = 0;
9477
9478   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9479
9480   if(!reg)
9481     return;
9482
9483   if(!endian) {
9484     endian = 1;
9485   } else {
9486     endian = -1;
9487     offset = size-1;
9488   }
9489
9490   while(size--) {
9491     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9492     offset += endian;
9493   }
9494
9495 }
9496
9497 #if !(USE_GENERIC_SIGNED_SHIFT)
9498 /*-----------------------------------------------------------------*/
9499 /* genLeftShift - generates code for left shifting                 */
9500 /*-----------------------------------------------------------------*/
9501 static void genLeftShift (iCode *ic)
9502 {
9503   operand *left,*right, *result;
9504   int size, offset;
9505 //  char *l;
9506   symbol *tlbl , *tlbl1;
9507   pCodeOp *pctemp;
9508
9509   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9510
9511   right = IC_RIGHT(ic);
9512   left  = IC_LEFT(ic);
9513   result = IC_RESULT(ic);
9514
9515   pic16_aopOp(right,ic,FALSE);
9516
9517   /* if the shift count is known then do it 
9518      as efficiently as possible */
9519   if (AOP_TYPE(right) == AOP_LIT) {
9520     pic16_genLeftShiftLiteral (left,right,result,ic);
9521     return ;
9522   }
9523
9524   /* shift count is unknown then we have to form
9525    * a loop. Get the loop count in WREG : Note: we take
9526    * only the lower order byte since shifting
9527    * more than 32 bits make no sense anyway, ( the
9528    * largest size of an object can be only 32 bits ) */
9529   
9530   pic16_aopOp(left,ic,FALSE);
9531   pic16_aopOp(result,ic,FALSE);
9532
9533   /* now move the left to the result if they are not the
9534    * same, and if size > 1,
9535    * and if right is not same to result (!!!) -- VR */
9536   if (!pic16_sameRegs(AOP(left),AOP(result))
9537       && (AOP_SIZE(result) > 1)) {
9538
9539     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9540
9541     size = AOP_SIZE(result);
9542     offset=0;
9543     while (size--) {
9544
9545 #if 0
9546       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9547       if (*l == '@' && (IS_AOP_PREG(result))) {
9548
9549           pic16_emitcode("mov","a,%s",l);
9550           pic16_aopPut(AOP(result),"a",offset);
9551       } else
9552 #endif
9553       {
9554         /* we don't know if left is a literal or a register, take care -- VR */
9555         pic16_mov2f(AOP(result), AOP(left), offset);
9556       }
9557       offset++;
9558     }
9559   }
9560
9561   size = AOP_SIZE(result);
9562
9563   /* if it is only one byte then */
9564   if (size == 1) {
9565     if(optimized_for_speed) {
9566       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9567       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9568       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9569       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9570       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9571       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9572       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9573       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9574       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9575       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9576       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9577       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9578     } else {
9579
9580       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9581
9582       tlbl = newiTempLabel(NULL);
9583
9584 #if 1
9585       /* this is already done, why change it? */
9586       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9587                 pic16_mov2f(AOP(result), AOP(left), 0);
9588       }
9589 #endif
9590
9591       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9592       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9593       pic16_emitpLabel(tlbl->key);
9594       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9595       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9596       emitSKPC;
9597       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9598     }
9599     goto release ;
9600   }
9601     
9602   if (pic16_sameRegs(AOP(left),AOP(result))) {
9603
9604     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9605     
9606     tlbl = newiTempLabel(NULL);
9607     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9608     genMultiAsm(POC_RRCF, result, size,1);
9609     pic16_emitpLabel(tlbl->key);
9610     genMultiAsm(POC_RLCF, result, size,0);
9611     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9612     emitSKPC;
9613     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9614     goto release;
9615   }
9616
9617   //tlbl = newiTempLabel(NULL);
9618   //offset = 0 ;   
9619   //tlbl1 = newiTempLabel(NULL);
9620
9621   //reAdjustPreg(AOP(result));    
9622     
9623   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9624   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9625   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9626   //MOVA(l);
9627   //pic16_emitcode("add","a,acc");         
9628   //pic16_aopPut(AOP(result),"a",offset++);
9629   //while (--size) {
9630   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9631   //  MOVA(l);
9632   //  pic16_emitcode("rlc","a");         
9633   //  pic16_aopPut(AOP(result),"a",offset++);
9634   //}
9635   //reAdjustPreg(AOP(result));
9636
9637   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9638   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9639
9640
9641   tlbl = newiTempLabel(NULL);
9642   tlbl1= newiTempLabel(NULL);
9643
9644   size = AOP_SIZE(result);
9645   offset = 1;
9646
9647   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9648
9649   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9650
9651   /* offset should be 0, 1 or 3 */
9652   
9653   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9654   emitSKPNZ;
9655   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9656
9657   pic16_emitpcode(POC_MOVWF, pctemp);
9658
9659
9660   pic16_emitpLabel(tlbl->key);
9661
9662   emitCLRC;
9663   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9664   while(--size)
9665     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9666
9667   pic16_emitpcode(POC_DECFSZ,  pctemp);
9668   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9669   pic16_emitpLabel(tlbl1->key);
9670
9671   pic16_popReleaseTempReg(pctemp,1);
9672
9673
9674  release:
9675   pic16_freeAsmop (right,NULL,ic,TRUE);
9676   pic16_freeAsmop(left,NULL,ic,TRUE);
9677   pic16_freeAsmop(result,NULL,ic,TRUE);
9678 }
9679 #endif
9680
9681
9682 #if 0
9683 #error old code (left here for reference)
9684 /*-----------------------------------------------------------------*/
9685 /* genLeftShift - generates code for left shifting                 */
9686 /*-----------------------------------------------------------------*/
9687 static void genLeftShift (iCode *ic)
9688 {
9689   operand *left,*right, *result;
9690   int size, offset;
9691   char *l;
9692   symbol *tlbl , *tlbl1;
9693   pCodeOp *pctemp;
9694
9695   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9696
9697   right = IC_RIGHT(ic);
9698   left  = IC_LEFT(ic);
9699   result = IC_RESULT(ic);
9700
9701   pic16_aopOp(right,ic,FALSE);
9702
9703   /* if the shift count is known then do it 
9704      as efficiently as possible */
9705   if (AOP_TYPE(right) == AOP_LIT) {
9706     pic16_genLeftShiftLiteral (left,right,result,ic);
9707     return ;
9708   }
9709
9710   /* shift count is unknown then we have to form 
9711      a loop get the loop count in B : Note: we take
9712      only the lower order byte since shifting
9713      more that 32 bits make no sense anyway, ( the
9714      largest size of an object can be only 32 bits ) */  
9715
9716     
9717   pic16_aopOp(left,ic,FALSE);
9718   pic16_aopOp(result,ic,FALSE);
9719
9720   /* now move the left to the result if they are not the
9721      same */
9722   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9723       AOP_SIZE(result) > 1) {
9724
9725     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9726
9727     size = AOP_SIZE(result);
9728     offset=0;
9729     while (size--) {
9730       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9731       if (*l == '@' && (IS_AOP_PREG(result))) {
9732
9733         pic16_emitcode("mov","a,%s",l);
9734         pic16_aopPut(AOP(result),"a",offset);
9735       } else {
9736
9737         /* we don't know if left is a literal or a register, take care -- VR */
9738         pic16_mov2f(AOP(result), AOP(left), offset);
9739       }
9740       offset++;
9741     }
9742   }
9743
9744   size = AOP_SIZE(result);
9745
9746   /* if it is only one byte then */
9747   if (size == 1) {
9748     if(optimized_for_speed) {
9749       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9750       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9751       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9752       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9753       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9754       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9755       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9756       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9757       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9758       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9759       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9760       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9761     } else {
9762
9763       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9764
9765       tlbl = newiTempLabel(NULL);
9766       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9767                 pic16_mov2f(AOP(result), AOP(left), 0);
9768                 
9769 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9770 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9771       }
9772
9773       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9774       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9775       pic16_emitpLabel(tlbl->key);
9776       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9777       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9778       emitSKPC;
9779       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9780     }
9781     goto release ;
9782   }
9783     
9784   if (pic16_sameRegs(AOP(left),AOP(result))) {
9785
9786     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9787     
9788     tlbl = newiTempLabel(NULL);
9789     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9790     genMultiAsm(POC_RRCF, result, size,1);
9791     pic16_emitpLabel(tlbl->key);
9792     genMultiAsm(POC_RLCF, result, size,0);
9793     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9794     emitSKPC;
9795     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9796     goto release;
9797   }
9798
9799   //tlbl = newiTempLabel(NULL);
9800   //offset = 0 ;   
9801   //tlbl1 = newiTempLabel(NULL);
9802
9803   //reAdjustPreg(AOP(result));    
9804     
9805   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9806   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9807   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9808   //MOVA(l);
9809   //pic16_emitcode("add","a,acc");         
9810   //pic16_aopPut(AOP(result),"a",offset++);
9811   //while (--size) {
9812   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9813   //  MOVA(l);
9814   //  pic16_emitcode("rlc","a");         
9815   //  pic16_aopPut(AOP(result),"a",offset++);
9816   //}
9817   //reAdjustPreg(AOP(result));
9818
9819   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9820   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9821
9822
9823   tlbl = newiTempLabel(NULL);
9824   tlbl1= newiTempLabel(NULL);
9825
9826   size = AOP_SIZE(result);
9827   offset = 1;
9828
9829   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9830
9831   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9832
9833   /* offset should be 0, 1 or 3 */
9834   
9835   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9836   emitSKPNZ;
9837   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9838
9839   pic16_emitpcode(POC_MOVWF, pctemp);
9840
9841
9842   pic16_emitpLabel(tlbl->key);
9843
9844   emitCLRC;
9845   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9846   while(--size)
9847     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9848
9849   pic16_emitpcode(POC_DECFSZ,  pctemp);
9850   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9851   pic16_emitpLabel(tlbl1->key);
9852
9853   pic16_popReleaseTempReg(pctemp,1);
9854
9855
9856  release:
9857   pic16_freeAsmop (right,NULL,ic,TRUE);
9858   pic16_freeAsmop(left,NULL,ic,TRUE);
9859   pic16_freeAsmop(result,NULL,ic,TRUE);
9860 }
9861 #endif
9862
9863 /*-----------------------------------------------------------------*/
9864 /* genrshOne - right shift a one byte quantity by known count      */
9865 /*-----------------------------------------------------------------*/
9866 static void genrshOne (operand *result, operand *left,
9867                        int shCount, int sign)
9868 {
9869     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9870     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9871 }
9872
9873 /*-----------------------------------------------------------------*/
9874 /* genrshTwo - right shift two bytes by known amount != 0          */
9875 /*-----------------------------------------------------------------*/
9876 static void genrshTwo (operand *result,operand *left,
9877                        int shCount, int sign)
9878 {
9879   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9880   /* if shCount >= 8 */
9881   if (shCount >= 8) {
9882     shCount -= 8 ;
9883     if (shCount)
9884       shiftR1Left2Result(left, MSB16, result, LSB,
9885                          shCount, sign);
9886     else
9887       movLeft2Result(left, MSB16, result, LSB);
9888
9889     pic16_addSign (result, 1, sign);
9890   }
9891
9892   /*  1 <= shCount <= 7 */
9893   else
9894     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9895 }
9896
9897 /*-----------------------------------------------------------------*/
9898 /* shiftRLong - shift right one long from left to result           */
9899 /* offl = LSB or MSB16                                             */
9900 /*-----------------------------------------------------------------*/
9901 static void shiftRLong (operand *left, int offl,
9902                         operand *result, int sign)
9903 {
9904     int size = AOP_SIZE(result);
9905     int same = pic16_sameRegs(AOP(left),AOP(result));
9906     int i;
9907     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9908
9909         if (same && (offl == MSB16)) { //shift one byte right
9910                 for(i=MSB16;i<size;i++) {
9911                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9912                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9913                 }
9914         }
9915
9916     if(sign)
9917                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9918         else
9919                 emitCLRC;
9920
9921         if (same) {
9922                 if (offl == LSB)
9923                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9924         } else {
9925         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9926         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9927         }
9928
9929     if(offl == MSB16) {
9930         /* add sign of "a" */
9931         pic16_addSign(result, MSB32, sign);
9932         }
9933
9934         if (same) {
9935         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9936         } else {
9937         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9938         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9939         }
9940         
9941         if (same) {
9942         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9943         } else {
9944         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9945         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9946         }
9947
9948         if (same) {
9949         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9950         } else {
9951         if(offl == LSB){
9952                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9953                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9954         }
9955         }
9956 }
9957
9958 /*-----------------------------------------------------------------*/
9959 /* genrshFour - shift four byte by a known amount != 0             */
9960 /*-----------------------------------------------------------------*/
9961 static void genrshFour (operand *result, operand *left,
9962                         int shCount, int sign)
9963 {
9964   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9965   /* if shifting more that 3 bytes */
9966   if(shCount >= 24 ) {
9967     shCount -= 24;
9968     if(shCount)
9969       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9970     else
9971       movLeft2Result(left, MSB32, result, LSB);
9972
9973     pic16_addSign(result, MSB16, sign);
9974   }
9975   else if(shCount >= 16){
9976     shCount -= 16;
9977     if(shCount)
9978       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9979     else{
9980       movLeft2Result(left, MSB24, result, LSB);
9981       movLeft2Result(left, MSB32, result, MSB16);
9982     }
9983     pic16_addSign(result, MSB24, sign);
9984   }
9985   else if(shCount >= 8){
9986     shCount -= 8;
9987     if(shCount == 1)
9988       shiftRLong(left, MSB16, result, sign);
9989     else if(shCount == 0){
9990       movLeft2Result(left, MSB16, result, LSB);
9991       movLeft2Result(left, MSB24, result, MSB16);
9992       movLeft2Result(left, MSB32, result, MSB24);
9993       pic16_addSign(result, MSB32, sign);
9994     }
9995     else{ //shcount >= 2
9996       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9997       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9998       /* the last shift is signed */
9999       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10000       pic16_addSign(result, MSB32, sign);
10001     }
10002   }
10003   else{   /* 1 <= shCount <= 7 */
10004     if(shCount <= 2){
10005       shiftRLong(left, LSB, result, sign);
10006       if(shCount == 2)
10007         shiftRLong(result, LSB, result, sign);
10008     }
10009     else{
10010       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10011       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10012       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10013     }
10014   }
10015 }
10016
10017 /*-----------------------------------------------------------------*/
10018 /* genRightShiftLiteral - right shifting by known count            */
10019 /*-----------------------------------------------------------------*/
10020 static void genRightShiftLiteral (operand *left,
10021                                   operand *right,
10022                                   operand *result,
10023                                   iCode *ic,
10024                                   int sign)
10025 {    
10026   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10027   int lsize,res_size;
10028
10029   pic16_freeAsmop(right,NULL,ic,TRUE);
10030
10031   pic16_aopOp(left,ic,FALSE);
10032   pic16_aopOp(result,ic,TRUE);
10033
10034   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10035
10036 #if VIEW_SIZE
10037   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10038                  AOP_SIZE(left));
10039 #endif
10040
10041   lsize = pic16_getDataSize(left);
10042   res_size = pic16_getDataSize(result);
10043   /* test the LEFT size !!! */
10044
10045   /* I suppose that the left size >= result size */
10046   if(shCount == 0){
10047     assert (res_size <= lsize);
10048     while (res_size--) {
10049       pic16_mov2f (AOP(result), AOP(left), res_size);
10050     } // for
10051   }
10052
10053   else if(shCount >= (lsize * 8)){
10054
10055     if(res_size == 1) {
10056       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10057       if(sign) {
10058         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10059         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10060       }
10061     } else {
10062
10063       if(sign) {
10064         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10065         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10066         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10067         while(res_size--)
10068           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10069
10070       } else {
10071
10072         while(res_size--)
10073           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10074       }
10075     }
10076   } else {
10077
10078     switch (res_size) {
10079     case 1:
10080       genrshOne (result,left,shCount,sign);
10081       break;
10082
10083     case 2:
10084       genrshTwo (result,left,shCount,sign);
10085       break;
10086
10087     case 4:
10088       genrshFour (result,left,shCount,sign);
10089       break;
10090     default :
10091       break;
10092     }
10093
10094   }
10095
10096   pic16_freeAsmop(left,NULL,ic,TRUE);
10097   pic16_freeAsmop(result,NULL,ic,TRUE);
10098 }
10099
10100 #if !(USE_GENERIC_SIGNED_SHIFT)
10101 /*-----------------------------------------------------------------*/
10102 /* genSignedRightShift - right shift of signed number              */
10103 /*-----------------------------------------------------------------*/
10104 static void genSignedRightShift (iCode *ic)
10105 {
10106   operand *right, *left, *result;
10107   int size, offset;
10108   //  char *l;
10109   symbol *tlbl, *tlbl1 ;
10110   pCodeOp *pctemp;
10111
10112   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10113
10114   /* we do it the hard way put the shift count in b
10115      and loop thru preserving the sign */
10116   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10117
10118   right = IC_RIGHT(ic);
10119   left  = IC_LEFT(ic);
10120   result = IC_RESULT(ic);
10121
10122   pic16_aopOp(right,ic,FALSE);  
10123   pic16_aopOp(left,ic,FALSE);
10124   pic16_aopOp(result,ic,FALSE);
10125
10126
10127   if ( AOP_TYPE(right) == AOP_LIT) {
10128     genRightShiftLiteral (left,right,result,ic,1);
10129     return ;
10130   }
10131   /* shift count is unknown then we have to form 
10132      a loop get the loop count in B : Note: we take
10133      only the lower order byte since shifting
10134      more that 32 bits make no sense anyway, ( the
10135      largest size of an object can be only 32 bits ) */  
10136
10137   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10138   //pic16_emitcode("inc","b");
10139   //pic16_freeAsmop (right,NULL,ic,TRUE);
10140   //pic16_aopOp(left,ic,FALSE);
10141   //pic16_aopOp(result,ic,FALSE);
10142
10143   /* now move the left to the result if they are not the
10144      same */
10145   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10146       AOP_SIZE(result) > 1) {
10147
10148     size = AOP_SIZE(result);
10149     offset=0;
10150     while (size--) { 
10151       /*
10152         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10153         if (*l == '@' && IS_AOP_PREG(result)) {
10154
10155         pic16_emitcode("mov","a,%s",l);
10156         pic16_aopPut(AOP(result),"a",offset);
10157         } else
10158         pic16_aopPut(AOP(result),l,offset);
10159       */
10160       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10161       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10162
10163       offset++;
10164     }
10165   }
10166
10167   /* mov the highest order bit to OVR */    
10168   tlbl = newiTempLabel(NULL);
10169   tlbl1= newiTempLabel(NULL);
10170
10171   size = AOP_SIZE(result);
10172   offset = size - 1;
10173
10174   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10175
10176   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10177
10178   /* offset should be 0, 1 or 3 */
10179   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10180   emitSKPNZ;
10181   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10182
10183   pic16_emitpcode(POC_MOVWF, pctemp);
10184
10185
10186   pic16_emitpLabel(tlbl->key);
10187
10188   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10189   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10190
10191   while(--size) {
10192     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10193   }
10194
10195   pic16_emitpcode(POC_DECFSZ,  pctemp);
10196   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10197   pic16_emitpLabel(tlbl1->key);
10198
10199   pic16_popReleaseTempReg(pctemp,1);
10200 #if 0
10201   size = AOP_SIZE(result);
10202   offset = size - 1;
10203   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10204   pic16_emitcode("rlc","a");
10205   pic16_emitcode("mov","ov,c");
10206   /* if it is only one byte then */
10207   if (size == 1) {
10208     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10209     MOVA(l);
10210     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10211     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10212     pic16_emitcode("mov","c,ov");
10213     pic16_emitcode("rrc","a");
10214     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10215     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10216     pic16_aopPut(AOP(result),"a",0);
10217     goto release ;
10218   }
10219
10220   reAdjustPreg(AOP(result));
10221   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10222   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10223   pic16_emitcode("mov","c,ov");
10224   while (size--) {
10225     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10226     MOVA(l);
10227     pic16_emitcode("rrc","a");         
10228     pic16_aopPut(AOP(result),"a",offset--);
10229   }
10230   reAdjustPreg(AOP(result));
10231   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10232   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10233
10234  release:
10235 #endif
10236
10237   pic16_freeAsmop(left,NULL,ic,TRUE);
10238   pic16_freeAsmop(result,NULL,ic,TRUE);
10239   pic16_freeAsmop(right,NULL,ic,TRUE);
10240 }
10241 #endif
10242
10243 #if !(USE_GENERIC_SIGNED_SHIFT)
10244 #warning This implementation of genRightShift() is incomplete!
10245 /*-----------------------------------------------------------------*/
10246 /* genRightShift - generate code for right shifting                */
10247 /*-----------------------------------------------------------------*/
10248 static void genRightShift (iCode *ic)
10249 {
10250     operand *right, *left, *result;
10251     sym_link *letype ;
10252     int size, offset;
10253     char *l;
10254     symbol *tlbl, *tlbl1 ;
10255
10256     /* if signed then we do it the hard way preserve the
10257     sign bit moving it inwards */
10258     letype = getSpec(operandType(IC_LEFT(ic)));
10259     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10260
10261     if (!SPEC_USIGN(letype)) {
10262         genSignedRightShift (ic);
10263         return ;
10264     }
10265
10266     /* signed & unsigned types are treated the same : i.e. the
10267     signed is NOT propagated inwards : quoting from the
10268     ANSI - standard : "for E1 >> E2, is equivalent to division
10269     by 2**E2 if unsigned or if it has a non-negative value,
10270     otherwise the result is implementation defined ", MY definition
10271     is that the sign does not get propagated */
10272
10273     right = IC_RIGHT(ic);
10274     left  = IC_LEFT(ic);
10275     result = IC_RESULT(ic);
10276
10277     pic16_aopOp(right,ic,FALSE);
10278
10279     /* if the shift count is known then do it 
10280     as efficiently as possible */
10281     if (AOP_TYPE(right) == AOP_LIT) {
10282         genRightShiftLiteral (left,right,result,ic, 0);
10283         return ;
10284     }
10285
10286     /* shift count is unknown then we have to form 
10287     a loop get the loop count in B : Note: we take
10288     only the lower order byte since shifting
10289     more that 32 bits make no sense anyway, ( the
10290     largest size of an object can be only 32 bits ) */  
10291
10292     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10293     pic16_emitcode("inc","b");
10294     pic16_aopOp(left,ic,FALSE);
10295     pic16_aopOp(result,ic,FALSE);
10296
10297     /* now move the left to the result if they are not the
10298     same */
10299     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10300         AOP_SIZE(result) > 1) {
10301
10302         size = AOP_SIZE(result);
10303         offset=0;
10304         while (size--) {
10305             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10306             if (*l == '@' && IS_AOP_PREG(result)) {
10307
10308                 pic16_emitcode("mov","a,%s",l);
10309                 pic16_aopPut(AOP(result),"a",offset);
10310             } else
10311                 pic16_aopPut(AOP(result),l,offset);
10312             offset++;
10313         }
10314     }
10315
10316     tlbl = newiTempLabel(NULL);
10317     tlbl1= newiTempLabel(NULL);
10318     size = AOP_SIZE(result);
10319     offset = size - 1;
10320
10321     /* if it is only one byte then */
10322     if (size == 1) {
10323
10324       tlbl = newiTempLabel(NULL);
10325       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10326         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10327         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10328       }
10329
10330       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10331       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10332       pic16_emitpLabel(tlbl->key);
10333       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10334       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10335       emitSKPC;
10336       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10337
10338       goto release ;
10339     }
10340
10341     reAdjustPreg(AOP(result));
10342     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10343     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10344     CLRC;
10345     while (size--) {
10346         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10347         MOVA(l);
10348         pic16_emitcode("rrc","a");         
10349         pic16_aopPut(AOP(result),"a",offset--);
10350     }
10351     reAdjustPreg(AOP(result));
10352
10353     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10354     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10355
10356 release:
10357     pic16_freeAsmop(left,NULL,ic,TRUE);
10358     pic16_freeAsmop (right,NULL,ic,TRUE);
10359     pic16_freeAsmop(result,NULL,ic,TRUE);
10360 }
10361 #endif
10362
10363 #if (USE_GENERIC_SIGNED_SHIFT)
10364 /*-----------------------------------------------------------------*/
10365 /* genGenericShift - generates code for left or right shifting     */
10366 /*-----------------------------------------------------------------*/
10367 static void genGenericShift (iCode *ic, int isShiftLeft) {
10368   operand *left,*right, *result;
10369   int offset;
10370   int sign, signedCount;
10371   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10372   PIC_OPCODE pos_shift, neg_shift;
10373
10374   FENTRY;
10375
10376   right = IC_RIGHT(ic);
10377   left  = IC_LEFT(ic);
10378   result = IC_RESULT(ic);
10379
10380   pic16_aopOp(right,ic,FALSE);
10381   pic16_aopOp(left,ic,FALSE);
10382   pic16_aopOp(result,ic,TRUE);
10383
10384   sign = !SPEC_USIGN(operandType (left));
10385   signedCount = !SPEC_USIGN(operandType (right));
10386
10387   /* if the shift count is known then do it 
10388      as efficiently as possible */
10389   if (AOP_TYPE(right) == AOP_LIT) {
10390     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10391     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10392     // we should modify right->aopu.aop_lit here!
10393     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10394     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10395     if (isShiftLeft)
10396       pic16_genLeftShiftLiteral (left,right,result,ic);
10397     else
10398       genRightShiftLiteral (left,right,result,ic, sign);
10399
10400     goto release;
10401   } // if (right is literal)
10402
10403   /* shift count is unknown then we have to form a loop.
10404    * Note: we take only the lower order byte since shifting
10405    * more than 32 bits make no sense anyway, ( the
10406    * largest size of an object can be only 32 bits )
10407    * Note: we perform arithmetic shifts if the left operand is
10408    * signed and we do an (effective) right shift, i. e. we
10409    * shift in the sign bit from the left. */
10410    
10411   label_complete = newiTempLabel ( NULL );
10412   label_loop_pos = newiTempLabel ( NULL );
10413   label_loop_neg = NULL;
10414   label_negative = NULL;
10415   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10416   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10417
10418   if (signedCount) {
10419     // additional labels needed
10420     label_loop_neg = newiTempLabel ( NULL );
10421     label_negative = newiTempLabel ( NULL );
10422   } // if
10423
10424   // copy source to result -- this will effectively truncate the left operand to the size of result!
10425   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10426   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10427   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10428     pic16_mov2f (AOP(result),AOP(left), offset);
10429   } // for
10430
10431   // if result is longer than left, fill with zeros (or sign)
10432   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10433     if (sign && AOP_SIZE(left) > 0) {
10434       // shift signed operand -- fill with sign
10435       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10436       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10437       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10438       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10439         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10440       } // for
10441     } else {
10442       // shift unsigned operand -- fill result with zeros
10443       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10444         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10445       } // for
10446     }
10447   } // if (size mismatch)
10448
10449   pic16_mov2w (AOP(right), 0);
10450   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10451   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10452   
10453 #if 0
10454   // perform a shift by one (shift count is positive)
10455   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10456   // 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])
10457   pic16_emitpLabel (label_loop_pos->key);
10458   emitCLRC;
10459   if (sign && (pos_shift == POC_RRCF)) {
10460     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10461     emitSETC;
10462   } // if
10463   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10464   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10465   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10466 #else
10467   // perform a shift by one (shift count is positive)
10468   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10469   // 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])
10470   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10471   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10472   emitCLRC;
10473   pic16_emitpLabel (label_loop_pos->key);
10474   if (sign && (pos_shift == POC_RRCF)) {
10475     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10476     emitSETC;
10477   } // if
10478   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10479   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10480   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10481   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10482 #endif
10483
10484   if (signedCount) {
10485     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10486
10487     pic16_emitpLabel (label_negative->key);
10488     // perform a shift by -1 (shift count is negative)
10489     // 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)
10490     emitCLRC;
10491     pic16_emitpLabel (label_loop_neg->key);
10492     if (sign && (neg_shift == POC_RRCF)) {
10493       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10494       emitSETC;
10495     } // if
10496     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10497     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10498     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10499     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10500   } // if (signedCount)
10501
10502   pic16_emitpLabel (label_complete->key);
10503
10504 release:
10505   pic16_freeAsmop (right,NULL,ic,TRUE);
10506   pic16_freeAsmop(left,NULL,ic,TRUE);
10507   pic16_freeAsmop(result,NULL,ic,TRUE);
10508 }
10509
10510 static void genLeftShift (iCode *ic) {
10511   genGenericShift (ic, 1);
10512 }
10513
10514 static void genRightShift (iCode *ic) {
10515   genGenericShift (ic, 0);
10516 }
10517 #endif
10518
10519
10520 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10521 void pic16_loadFSR0(operand *op, int lit)
10522 {
10523   if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10524     pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10525   } else {
10526     assert (!OP_SYMBOL(op)->remat);
10527     // set up FSR0 with address of result
10528     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10529     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10530   }
10531 }
10532
10533 /*----------------------------------------------------------------*/
10534 /* pic16_derefPtr - move one byte from the location ptr points to */
10535 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10536 /*                  to the location ptr points to (doWrite != 0)   */
10537 /*----------------------------------------------------------------*/
10538 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10539 {
10540   switch (p_type) {
10541     case FPOINTER:
10542     case POINTER:
10543       if (!fsr0_setup || !*fsr0_setup)
10544       {
10545         pic16_loadFSR0( ptr, 0 );
10546         if (fsr0_setup) *fsr0_setup = 1;
10547       }
10548       if (doWrite)
10549         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10550       else
10551         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10552       break;
10553
10554     case GPOINTER:
10555       if (AOP(ptr)->aopu.aop_reg[2]) {
10556         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10557         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10558         pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10559         pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),1), pic16_popCopyReg(&pic16_pc_prodl)));
10560         pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(ptr),2));
10561         pic16_callGenericPointerRW(doWrite, 1);
10562       } else {
10563         // data pointer (just 2 byte given)
10564         if (!fsr0_setup || !*fsr0_setup)
10565         {
10566           pic16_loadFSR0( ptr, 0 );
10567           if (fsr0_setup) *fsr0_setup = 1;
10568         }
10569         if (doWrite)
10570           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10571         else
10572           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10573       }
10574       break;
10575
10576     default:
10577       assert (0 && "invalid pointer type specified");
10578       break;
10579   }
10580 }
10581
10582 /*-----------------------------------------------------------------*/
10583 /* genUnpackBits - generates code for unpacking bits               */
10584 /*-----------------------------------------------------------------*/
10585 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10586 {    
10587   int shCnt ;
10588   sym_link *etype, *letype;
10589   int blen=0, bstr=0;
10590   int lbstr;
10591
10592     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10593     etype = getSpec(operandType(result));
10594     letype = getSpec(operandType(left));
10595     
10596 //    if(IS_BITFIELD(etype)) {
10597       blen = SPEC_BLEN(etype);
10598       bstr = SPEC_BSTR(etype);
10599 //    }
10600
10601     lbstr = SPEC_BSTR( letype );
10602
10603 #if 1
10604     if((blen == 1) && (bstr < 8)) {
10605       /* it is a single bit, so use the appropriate bit instructions */
10606       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10607
10608       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10609       
10610       // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10611       if(!IS_PTR(operandType(left))/* && OP_SYMBOL(left)->remat && (ptype == POINTER)*/) {
10612         /* workaround to reduce the extra lfsr instruction */
10613         pic16_emitpcode(POC_BTFSC,
10614               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10615       } else {
10616         pic16_loadFSR0 (left, 0);
10617         pic16_emitpcode(POC_BTFSC,
10618               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10619       }
10620         
10621       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10622
10623       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10624       return;
10625     }
10626
10627 #endif
10628
10629         /* the following call to pic16_loadFSR0 is temporary until
10630          * optimization to handle single bit assignments is added
10631          * to the function. Until then use the old safe way! -- VR */
10632
10633     if (!IS_PTR(operandType(left)) /*OP_SYMBOL(left)->remat*/) {
10634         // access symbol directly
10635         pic16_mov2w (AOP(left), 0);
10636     } else {
10637       pic16_derefPtr (left, ptype, 0, NULL);
10638     }
10639
10640         /* if we have bitdisplacement then it fits   */
10641         /* into this byte completely or if length is */
10642         /* less than a byte                          */
10643         if ((shCnt = SPEC_BSTR(etype)) || 
10644                 (SPEC_BLEN(etype) <= 8))  {
10645
10646                 /* shift right acc */
10647                 AccRsh(shCnt, 0);
10648
10649                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10650                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10651
10652 /* VR -- normally I would use the following, but since we use the hack,
10653  * to avoid the masking from AccRsh, why not mask it right now? */
10654
10655 /*
10656                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10657 */
10658
10659                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10660           return ;
10661         }
10662
10663
10664
10665         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10666         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10667         exit(-1);
10668
10669     return ;
10670 }
10671
10672
10673 static void genDataPointerGet(operand *left,
10674                               operand *result,
10675                               iCode *ic)
10676 {
10677   int size, offset = 0, leoffset=0 ;
10678
10679         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10680         pic16_aopOp(result, ic, TRUE);
10681
10682         FENTRY;
10683
10684         size = AOP_SIZE(result);
10685 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10686
10687
10688 #if 0
10689         /* The following tests may save a redudant movff instruction when
10690          * accessing unions */
10691          
10692         /* if they are the same */
10693         if (operandsEqu (left, result)) {
10694                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10695                 goto release;
10696         }
10697 #endif
10698
10699 #if 0
10700         /* if they are the same registers */
10701         if (pic16_sameRegs(AOP(left),AOP(result))) {
10702                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10703                 goto release;
10704         }
10705 #endif
10706
10707 #if 1
10708         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10709                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10710                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10711                 goto release;
10712         }
10713 #endif
10714
10715
10716 #if 0
10717         if ( AOP_TYPE(left) == AOP_PCODE) {
10718                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
10719                                 AOP(left)->aopu.pcop->name,
10720                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
10721                                 PCOR(AOP(left)->aopu.pcop)->instance:
10722                                 PCOI(AOP(left)->aopu.pcop)->offset);
10723         }
10724 #endif
10725
10726         if(AOP(left)->aopu.pcop->type == PO_DIR)
10727                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10728
10729         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10730
10731         while (size--) {
10732                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10733                 
10734 //              pic16_DumpOp("(result)",result);
10735                 if(is_LitAOp(AOP(result))) {
10736                         pic16_mov2w(AOP(left), offset); // patch 8
10737                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10738                 } else {
10739                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10740                                 pic16_popGet(AOP(left), offset), //patch 8
10741                                 pic16_popGet(AOP(result), offset)));
10742                 }
10743
10744                 offset++;
10745                 leoffset++;
10746         }
10747
10748 release:
10749     pic16_freeAsmop(result,NULL,ic,TRUE);
10750 }
10751
10752
10753
10754 /*-----------------------------------------------------------------*/
10755 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10756 /*-----------------------------------------------------------------*/
10757 static void genNearPointerGet (operand *left, 
10758                                operand *result, 
10759                                iCode *ic)
10760 {
10761 //  asmop *aop = NULL;
10762   //regs *preg = NULL ;
10763   sym_link *rtype, *retype;
10764   sym_link *ltype, *letype;
10765
10766     FENTRY;
10767     
10768     rtype = operandType(result);
10769     retype= getSpec(rtype);
10770     ltype = operandType(left);
10771     letype= getSpec(ltype);
10772     
10773     pic16_aopOp(left,ic,FALSE);
10774
10775 //    pic16_DumpOp("(left)",left);
10776 //    pic16_DumpOp("(result)",result);
10777
10778     /* if left is rematerialisable and
10779      * result is not bit variable type and
10780      * the left is pointer to data space i.e
10781      * lower 128 bytes of space */
10782     
10783     if (AOP_TYPE(left) == AOP_PCODE
10784       && !IS_BITFIELD(retype)
10785       && DCL_TYPE(ltype) == POINTER) {
10786
10787         genDataPointerGet (left,result,ic);
10788         pic16_freeAsmop(left, NULL, ic, TRUE);
10789         return ;
10790     }
10791     
10792     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10793     pic16_aopOp (result,ic,TRUE);
10794     
10795     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10796
10797 #if 1
10798     if(IS_BITFIELD( retype )
10799       && (SPEC_BLEN(operandType(result))==1)
10800     ) {
10801       iCode *nextic;
10802       pCodeOp *jop;
10803       int bitstrt, bytestrt;
10804
10805         /* if this is bitfield of size 1, see if we are checking the value
10806          * of a single bit in an if-statement,
10807          * if yes, then don't generate usual code, but execute the
10808          * genIfx directly -- VR */
10809
10810         nextic = ic->next;
10811
10812         /* CHECK: if next iCode is IFX
10813          * and current result operand is nextic's conditional operand
10814          * and current result operand live ranges ends at nextic's key number
10815          */
10816         if((nextic->op == IFX)
10817           && (result == IC_COND(nextic))
10818           && (OP_LIVETO(result) == nextic->seq)
10819           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10820           ) {
10821             /* everything is ok then */
10822             /* find a way to optimize the genIfx iCode */
10823
10824             bytestrt = SPEC_BSTR(operandType(result))/8;
10825             bitstrt = SPEC_BSTR(operandType(result))%8;
10826             
10827             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10828
10829             genIfxpCOpJump(nextic, jop);
10830             
10831             pic16_freeAsmop(left, NULL, ic, TRUE);
10832             pic16_freeAsmop(result, NULL, ic, TRUE);
10833             return;
10834         }
10835     }
10836 #endif
10837
10838     /* if bitfield then unpack the bits */
10839     if (IS_BITFIELD(letype)) 
10840       genUnpackBits (result, left, NULL, POINTER);
10841     else {
10842       /* we have can just get the values */
10843       int size = AOP_SIZE(result);
10844       int offset = 0;   
10845         
10846       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10847
10848       pic16_loadFSR0( left, 0 );
10849
10850       while(size--) {
10851         if(size) {
10852           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10853                 pic16_popGet(AOP(result), offset++)));
10854         } else {
10855           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10856                 pic16_popGet(AOP(result), offset++)));
10857         }
10858       }
10859     }
10860
10861 #if 0
10862     /* now some housekeeping stuff */
10863     if (aop) {
10864       /* we had to allocate for this iCode */
10865       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10866       pic16_freeAsmop(NULL,aop,ic,TRUE);
10867     } else { 
10868       /* we did not allocate which means left
10869        * already in a pointer register, then
10870        * if size > 0 && this could be used again
10871        * we have to point it back to where it 
10872        * belongs */
10873       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10874       if (AOP_SIZE(result) > 1
10875         && !OP_SYMBOL(left)->remat
10876         && ( OP_SYMBOL(left)->liveTo > ic->seq
10877             || ic->depth )) {
10878 //        int size = AOP_SIZE(result) - 1;
10879 //        while (size--)
10880 //          pic16_emitcode("dec","%s",rname);
10881         }
10882     }
10883 #endif
10884
10885     /* done */
10886     pic16_freeAsmop(left,NULL,ic,TRUE);
10887     pic16_freeAsmop(result,NULL,ic,TRUE);
10888 }
10889
10890 /*-----------------------------------------------------------------*/
10891 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10892 /*-----------------------------------------------------------------*/
10893 static void genPagedPointerGet (operand *left, 
10894                                operand *result, 
10895                                iCode *ic)
10896 {
10897     asmop *aop = NULL;
10898     regs *preg = NULL ;
10899     char *rname ;
10900     sym_link *rtype, *retype;    
10901
10902     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10903
10904     rtype = operandType(result);
10905     retype= getSpec(rtype);
10906     
10907     pic16_aopOp(left,ic,FALSE);
10908
10909   /* if the value is already in a pointer register
10910        then don't need anything more */
10911     if (!AOP_INPREG(AOP(left))) {
10912         /* otherwise get a free pointer register */
10913         aop = newAsmop(0);
10914         preg = getFreePtr(ic,&aop,FALSE);
10915         pic16_emitcode("mov","%s,%s",
10916                 preg->name,
10917                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10918         rname = preg->name ;
10919     } else
10920         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10921     
10922     pic16_freeAsmop(left,NULL,ic,TRUE);
10923     pic16_aopOp (result,ic,TRUE);
10924
10925     /* if bitfield then unpack the bits */
10926     if (IS_BITFIELD(retype)) 
10927         genUnpackBits (result,left,rname,PPOINTER);
10928     else {
10929         /* we have can just get the values */
10930         int size = AOP_SIZE(result);
10931         int offset = 0 ;        
10932         
10933         while (size--) {
10934             
10935             pic16_emitcode("movx","a,@%s",rname);
10936             pic16_aopPut(AOP(result),"a",offset);
10937             
10938             offset++ ;
10939             
10940             if (size)
10941                 pic16_emitcode("inc","%s",rname);
10942         }
10943     }
10944
10945     /* now some housekeeping stuff */
10946     if (aop) {
10947         /* we had to allocate for this iCode */
10948         pic16_freeAsmop(NULL,aop,ic,TRUE);
10949     } else { 
10950         /* we did not allocate which means left
10951            already in a pointer register, then
10952            if size > 0 && this could be used again
10953            we have to point it back to where it 
10954            belongs */
10955         if (AOP_SIZE(result) > 1 &&
10956             !OP_SYMBOL(left)->remat &&
10957             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10958               ic->depth )) {
10959             int size = AOP_SIZE(result) - 1;
10960             while (size--)
10961                 pic16_emitcode("dec","%s",rname);
10962         }
10963     }
10964
10965     /* done */
10966     pic16_freeAsmop(result,NULL,ic,TRUE);
10967     
10968         
10969 }
10970
10971 /*-----------------------------------------------------------------*/
10972 /* genFarPointerGet - gget value from far space                    */
10973 /*-----------------------------------------------------------------*/
10974 static void genFarPointerGet (operand *left,
10975                               operand *result, iCode *ic)
10976 {
10977     int size, offset ;
10978     sym_link *retype = getSpec(operandType(result));
10979
10980     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10981
10982     pic16_aopOp(left,ic,FALSE);
10983
10984     /* if the operand is already in dptr 
10985     then we do nothing else we move the value to dptr */
10986     if (AOP_TYPE(left) != AOP_STR) {
10987         /* if this is remateriazable */
10988         if (AOP_TYPE(left) == AOP_IMMD)
10989             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10990         else { /* we need to get it byte by byte */
10991             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10992             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10993             if (options.model == MODEL_FLAT24)
10994             {
10995                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10996             }
10997         }
10998     }
10999     /* so dptr know contains the address */
11000     pic16_freeAsmop(left,NULL,ic,TRUE);
11001     pic16_aopOp(result,ic,TRUE);
11002
11003     /* if bit then unpack */
11004     if (IS_BITFIELD(retype)) 
11005         genUnpackBits(result,left,"dptr",FPOINTER);
11006     else {
11007         size = AOP_SIZE(result);
11008         offset = 0 ;
11009
11010         while (size--) {
11011             pic16_emitcode("movx","a,@dptr");
11012             pic16_aopPut(AOP(result),"a",offset++);
11013             if (size)
11014                 pic16_emitcode("inc","dptr");
11015         }
11016     }
11017
11018     pic16_freeAsmop(result,NULL,ic,TRUE);
11019 }
11020
11021 #if 0
11022 /*-----------------------------------------------------------------*/
11023 /* genCodePointerGet - get value from code space                  */
11024 /*-----------------------------------------------------------------*/
11025 static void genCodePointerGet (operand *left,
11026                                 operand *result, iCode *ic)
11027 {
11028     int size, offset ;
11029     sym_link *retype = getSpec(operandType(result));
11030
11031     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11032
11033     pic16_aopOp(left,ic,FALSE);
11034
11035     /* if the operand is already in dptr 
11036     then we do nothing else we move the value to dptr */
11037     if (AOP_TYPE(left) != AOP_STR) {
11038         /* if this is remateriazable */
11039         if (AOP_TYPE(left) == AOP_IMMD)
11040             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11041         else { /* we need to get it byte by byte */
11042             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11043             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11044             if (options.model == MODEL_FLAT24)
11045             {
11046                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11047             }
11048         }
11049     }
11050     /* so dptr know contains the address */
11051     pic16_freeAsmop(left,NULL,ic,TRUE);
11052     pic16_aopOp(result,ic,FALSE);
11053
11054     /* if bit then unpack */
11055     if (IS_BITFIELD(retype)) 
11056         genUnpackBits(result,left,"dptr",CPOINTER);
11057     else {
11058         size = AOP_SIZE(result);
11059         offset = 0 ;
11060
11061         while (size--) {
11062             pic16_emitcode("clr","a");
11063             pic16_emitcode("movc","a,@a+dptr");
11064             pic16_aopPut(AOP(result),"a",offset++);
11065             if (size)
11066                 pic16_emitcode("inc","dptr");
11067         }
11068     }
11069
11070     pic16_freeAsmop(result,NULL,ic,TRUE);
11071 }
11072 #endif
11073
11074 #if 0
11075 /*-----------------------------------------------------------------*/
11076 /* genGenPointerGet - gget value from generic pointer space        */
11077 /*-----------------------------------------------------------------*/
11078 static void genGenPointerGet (operand *left,
11079                               operand *result, iCode *ic)
11080 {
11081   int size, offset, lit;
11082   sym_link *retype = getSpec(operandType(result));
11083
11084         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11085         pic16_aopOp(left,ic,FALSE);
11086         pic16_aopOp(result,ic,FALSE);
11087         size = AOP_SIZE(result);
11088
11089         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11090
11091         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11092
11093                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11094                 // load FSR0 from immediate
11095                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11096
11097 //              pic16_loadFSR0( left );
11098
11099                 offset = 0;
11100                 while(size--) {
11101                         if(size) {
11102                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11103                         } else {
11104                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11105                         }
11106                         offset++;
11107                 }
11108                 goto release;
11109
11110         }
11111         else { /* we need to get it byte by byte */
11112                 // set up FSR0 with address from left
11113                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11114                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11115                 
11116                 offset = 0 ;
11117
11118                 while(size--) {
11119                         if(size) {
11120                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11121                         } else {
11122                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11123                         }
11124                         offset++;
11125                 }
11126                 goto release;
11127         }
11128
11129   /* if bit then unpack */
11130         if (IS_BITFIELD(retype)) 
11131                 genUnpackBits(result,left,"BAD",GPOINTER);
11132
11133         release:
11134         pic16_freeAsmop(left,NULL,ic,TRUE);
11135         pic16_freeAsmop(result,NULL,ic,TRUE);
11136
11137 }
11138 #endif
11139
11140
11141 /*-----------------------------------------------------------------*/
11142 /* genGenPointerGet - gget value from generic pointer space        */
11143 /*-----------------------------------------------------------------*/
11144 static void genGenPointerGet (operand *left,
11145                               operand *result, iCode *ic)
11146 {
11147   int size, offset, lit;
11148   sym_link *letype = getSpec(operandType(left));
11149
11150     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11151     pic16_aopOp(left,ic,FALSE);
11152     pic16_aopOp(result,ic,TRUE);
11153     size = AOP_SIZE(result);
11154
11155     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11156   
11157     /* if bit then unpack */
11158     if (IS_BITFIELD(letype)) {
11159       genUnpackBits(result,left,"BAD",GPOINTER);
11160       goto release;
11161     }
11162
11163     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11164
11165       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11166       // load FSR0 from immediate
11167       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11168
11169       werror(W_POSSBUG2, __FILE__, __LINE__);
11170
11171       offset = 0;
11172       while(size--) {
11173         if(size) {
11174           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11175         } else {
11176           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11177         }
11178         offset++;
11179       }
11180
11181       goto release;
11182
11183     } else { /* we need to get it byte by byte */
11184
11185       /* set up WREG:PRODL:FSR0L with address from left */
11186       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11187       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11188       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11189       
11190       pic16_callGenericPointerRW(0, size);
11191       
11192       assignResultValue(result, 1);
11193       
11194       goto release;
11195     }
11196
11197 release:
11198   pic16_freeAsmop(left,NULL,ic,TRUE);
11199   pic16_freeAsmop(result,NULL,ic,TRUE);
11200 }
11201
11202 /*-----------------------------------------------------------------*/
11203 /* genConstPointerGet - get value from const generic pointer space */
11204 /*-----------------------------------------------------------------*/
11205 static void genConstPointerGet (operand *left,
11206                                 operand *result, iCode *ic)
11207 {
11208   //sym_link *retype = getSpec(operandType(result));
11209   // symbol *albl = newiTempLabel(NULL);        // patch 15
11210   // symbol *blbl = newiTempLabel(NULL);        //
11211   // PIC_OPCODE poc;                            // patch 15
11212   int size;
11213   int offset = 0;
11214
11215   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11216   pic16_aopOp(left,ic,FALSE);
11217   pic16_aopOp(result,ic,TRUE);
11218   size = AOP_SIZE(result);
11219
11220   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11221
11222   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11223
11224   // set up table pointer
11225   if( (AOP_TYPE(left) == AOP_PCODE) 
11226       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11227           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11228     {
11229       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11230       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11231       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11232       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11233       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11234       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11235   } else {
11236     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11237     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11238     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11239   }
11240
11241   while(size--) {
11242     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11243     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11244     offset++;
11245   }
11246     
11247   pic16_freeAsmop(left,NULL,ic,TRUE);
11248   pic16_freeAsmop(result,NULL,ic,TRUE);
11249 }
11250
11251
11252 /*-----------------------------------------------------------------*/
11253 /* genPointerGet - generate code for pointer get                   */
11254 /*-----------------------------------------------------------------*/
11255 static void genPointerGet (iCode *ic)
11256 {
11257   operand *left, *result ;
11258   sym_link *type, *etype;
11259   int p_type;
11260
11261     FENTRY;
11262     
11263     left = IC_LEFT(ic);
11264     result = IC_RESULT(ic) ;
11265
11266     /* depending on the type of pointer we need to
11267     move it to the correct pointer register */
11268     type = operandType(left);
11269     etype = getSpec(type);
11270
11271 #if 0
11272     if (IS_PTR_CONST(type))
11273 #else
11274     if (IS_CODEPTR(type))
11275 #endif
11276       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11277
11278     /* if left is of type of pointer then it is simple */
11279     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11280       p_type = DCL_TYPE(type);
11281     else {
11282       /* we have to go by the storage class */
11283       p_type = PTR_TYPE(SPEC_OCLS(etype));
11284
11285       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11286
11287       if (SPEC_OCLS(etype)->codesp ) {
11288         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11289         //p_type = CPOINTER ;   
11290       } else
11291       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11292         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11293         /*p_type = FPOINTER ;*/ 
11294       } else
11295       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11296         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11297         /* p_type = PPOINTER; */
11298       } else
11299       if (SPEC_OCLS(etype) == idata ) {
11300         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11301         /* p_type = IPOINTER; */
11302       } else {
11303         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11304         /* p_type = POINTER ; */
11305       }
11306     }
11307
11308     /* now that we have the pointer type we assign
11309     the pointer values */
11310     switch (p_type) {
11311       case POINTER:     
11312       case IPOINTER:
11313         genNearPointerGet (left,result,ic);
11314         break;
11315
11316       case PPOINTER:
11317         genPagedPointerGet(left,result,ic);
11318         break;
11319
11320       case FPOINTER:
11321         genFarPointerGet (left,result,ic);
11322         break;
11323
11324       case CPOINTER:
11325         genConstPointerGet (left,result,ic);
11326         //pic16_emitcodePointerGet (left,result,ic);
11327         break;
11328
11329       case GPOINTER:
11330 #if 0
11331       if (IS_PTR_CONST(type))
11332         genConstPointerGet (left,result,ic);
11333       else
11334 #endif
11335         genGenPointerGet (left,result,ic);
11336       break;
11337
11338     default:
11339       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11340               "genPointerGet: illegal pointer type");
11341     
11342     }
11343 }
11344
11345 /*-----------------------------------------------------------------*/
11346 /* genPackBits - generates code for packed bit storage             */
11347 /*-----------------------------------------------------------------*/
11348 static void genPackBits (sym_link    *etype , operand *result,
11349                          operand *right ,
11350                          char *rname, int p_type)
11351 {
11352   int shCnt = 0 ;
11353   int offset = 0  ;
11354   int rLen = 0 ;
11355   int blen, bstr ;   
11356   sym_link *retype;
11357
11358         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11359         blen = SPEC_BLEN(etype);
11360         bstr = SPEC_BSTR(etype);
11361
11362         retype = getSpec(operandType(right));
11363
11364         if(AOP_TYPE(right) == AOP_LIT) {
11365                 if((blen == 1) && (bstr < 8)) {
11366                   unsigned long lit;
11367                         /* it is a single bit, so use the appropriate bit instructions */
11368
11369                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11370
11371                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11372 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11373                         if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11374                                 /* workaround to reduce the extra lfsr instruction */
11375                                 if(lit) {
11376                                         pic16_emitpcode(POC_BSF,
11377                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11378                                 } else {
11379                                         pic16_emitpcode(POC_BCF,
11380                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11381                                 }
11382                         } else {
11383                                 pic16_loadFSR0(result, 0);
11384                                 if(lit) {
11385                                         pic16_emitpcode(POC_BSF,
11386                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11387                                 } else {
11388                                         pic16_emitpcode(POC_BCF,
11389                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11390                                 }
11391                         }
11392         
11393                   return;
11394                 }
11395                 /* move literal to W */
11396                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11397                 offset++;
11398         } else
11399         if(IS_BITFIELD(retype) 
11400           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11401           && (blen == 1)) {
11402           int rblen, rbstr;
11403
11404             rblen = SPEC_BLEN( retype );
11405             rbstr = SPEC_BSTR( retype );
11406             
11407
11408             if(IS_BITFIELD(etype)) {
11409               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11410               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11411             } else {
11412               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11413             }
11414             
11415             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11416             
11417             if(IS_BITFIELD(etype)) {
11418               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11419             } else {
11420               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11421             }
11422
11423             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11424             
11425             return;
11426         } else {
11427           /* move right to W */
11428           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11429         }
11430
11431         /* if the bit length is less than or   */
11432         /* it exactly fits a byte then         */
11433         if((shCnt=SPEC_BSTR(etype))
11434                 || SPEC_BLEN(etype) <= 8 )  {
11435                 int fsr0_setup = 0;
11436
11437                 if (blen != 8 || bstr != 0) {
11438                   // we need to combine the value with the old value
11439                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11440
11441           DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11442                 SPEC_BSTR(etype), SPEC_BLEN(etype));
11443                 
11444                   /* shift left acc */
11445                   AccLsh(shCnt);
11446
11447                   /* using PRODH as a temporary register here */
11448                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11449
11450                   if (IS_SYMOP(result) && !IS_PTR(operandType (result))/*OP_SYMBOL(result)->remat*/) {
11451                     /* access symbol directly */
11452                     pic16_mov2w (AOP(result), 0);
11453                   } else {
11454                     /* get old value */
11455                     pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11456                   }
11457 #if 1
11458                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11459                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11460                                         (unsigned char)(0xff >> (8-bstr))) ));
11461                   pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11462                 } // if (blen != 8 || bstr != 0)
11463
11464                 /* write new value back */
11465                 if (IS_SYMOP(result) & !IS_PTR(operandType(result))) {
11466                   pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11467                 } else {
11468                   pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11469                }
11470 #endif
11471
11472           return;
11473         }
11474
11475
11476 #if 0
11477         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11478         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11479         exit(-1);
11480 #endif
11481
11482
11483     pic16_loadFSR0(result, 0);                  // load FSR0 with address of result
11484     rLen = SPEC_BLEN(etype)-8;
11485     
11486     /* now generate for lengths greater than one byte */
11487     while (1) {
11488         rLen -= 8 ;
11489         if (rLen <= 0 ) {
11490           mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11491           break ;
11492         }
11493
11494         switch (p_type) {
11495             case POINTER:
11496                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11497                 break;
11498
11499 /*
11500             case FPOINTER:
11501                 MOVA(l);
11502                 pic16_emitcode("movx","@dptr,a");
11503                 break;
11504
11505             case GPOINTER:
11506                 MOVA(l);
11507                 DEBUGpic16_emitcode(";lcall","__gptrput");
11508                 break;  
11509 */
11510           default:
11511             assert(0);
11512         }   
11513
11514
11515         pic16_mov2w(AOP(right), offset++);
11516     }
11517
11518     /* last last was not complete */
11519     if (rLen)   {
11520         /* save the byte & read byte */
11521         switch (p_type) {
11522             case POINTER:
11523 //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11524                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11525                 break;
11526
11527 /*
11528             case FPOINTER:
11529                 pic16_emitcode ("mov","b,a");
11530                 pic16_emitcode("movx","a,@dptr");
11531                 break;
11532
11533             case GPOINTER:
11534                 pic16_emitcode ("push","b");
11535                 pic16_emitcode ("push","acc");
11536                 pic16_emitcode ("lcall","__gptrget");
11537                 pic16_emitcode ("pop","b");
11538                 break;
11539 */
11540             default:
11541               assert(0);
11542         }
11543         DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11544         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11545         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11546 //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11547 //        pic16_emitcode ("orl","a,b");
11548     }
11549
11550 //    if (p_type == GPOINTER)
11551 //        pic16_emitcode("pop","b");
11552
11553     switch (p_type) {
11554
11555       case POINTER:
11556         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11557 //      pic16_emitcode("mov","@%s,a",rname);
11558         break;
11559 /*
11560       case FPOINTER:
11561         pic16_emitcode("movx","@dptr,a");
11562         break;
11563         
11564       case GPOINTER:
11565         DEBUGpic16_emitcode(";lcall","__gptrput");
11566         break;                  
11567 */
11568       default:
11569         assert(0);
11570     }
11571     
11572 //    pic16_freeAsmop(right, NULL, ic, TRUE);
11573 }
11574 /*-----------------------------------------------------------------*/
11575 /* genDataPointerSet - remat pointer to data space                 */
11576 /*-----------------------------------------------------------------*/
11577 static void genDataPointerSet(operand *right,
11578                               operand *result,
11579                               iCode *ic)
11580 {
11581     int size, offset = 0, resoffset=0 ;
11582
11583     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11584     pic16_aopOp(right,ic,FALSE);
11585
11586     size = AOP_SIZE(right);
11587
11588 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11589
11590 #if 0
11591     if ( AOP_TYPE(result) == AOP_PCODE) {
11592       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11593               AOP(result)->aopu.pcop->name,
11594                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11595               PCOR(AOP(result)->aopu.pcop)->instance:
11596               PCOI(AOP(result)->aopu.pcop)->offset);
11597     }
11598 #endif
11599
11600         if(AOP(result)->aopu.pcop->type == PO_DIR)
11601                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11602
11603         while (size--) {
11604                 if (AOP_TYPE(right) == AOP_LIT) {
11605                   unsigned int lit;
11606
11607                     if(!IS_FLOAT(operandType( right )))
11608                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11609                     else {
11610                       union {
11611                         unsigned long lit_int;
11612                         float lit_float;
11613                       } info;
11614         
11615                         /* take care if literal is a float */
11616                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11617                         lit = info.lit_int;
11618                     }
11619
11620                     lit = lit >> (8*offset);
11621                     if(lit&0xff) {
11622                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11623                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11624                     } else {
11625                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11626                     }
11627                 } else {
11628                   pic16_mov2w(AOP(right), offset);
11629                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11630                 }
11631                 offset++;
11632                 resoffset++;
11633         }
11634
11635     pic16_freeAsmop(right,NULL,ic,TRUE);
11636 }
11637
11638
11639
11640 /*-----------------------------------------------------------------*/
11641 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11642 /*-----------------------------------------------------------------*/
11643 static void genNearPointerSet (operand *right,
11644                                operand *result, 
11645                                iCode *ic)
11646 {
11647   asmop *aop = NULL;
11648   sym_link *retype;
11649   sym_link *ptype = operandType(result);
11650   sym_link *resetype;
11651     
11652         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11653         retype= getSpec(operandType(right));
11654         resetype = getSpec(operandType(result));
11655   
11656         pic16_aopOp(result,ic,FALSE);
11657     
11658         /* if the result is rematerializable &
11659          * in data space & not a bit variable */
11660         
11661         /* and result is not a bit variable */
11662         if (AOP_TYPE(result) == AOP_PCODE
11663 //              && AOP_TYPE(result) == AOP_IMMD
11664                 && DCL_TYPE(ptype) == POINTER
11665                 && !IS_BITFIELD(retype)
11666                 && !IS_BITFIELD(resetype)) {
11667
11668                 genDataPointerSet (right,result,ic);
11669                 pic16_freeAsmop(result,NULL,ic,TRUE);
11670           return;
11671         }
11672
11673         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11674         pic16_aopOp(right,ic,FALSE);
11675         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11676
11677         /* if bitfield then unpack the bits */
11678         if (IS_BITFIELD(resetype)) {
11679                 genPackBits (resetype, result, right, NULL, POINTER);
11680         } else {
11681                 /* we have can just get the values */
11682           int size = AOP_SIZE(right);
11683           int offset = 0 ;    
11684
11685             pic16_loadFSR0(result, 0);
11686             
11687                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11688                 while (size--) {
11689                                 if (AOP_TYPE(right) == AOP_LIT) {
11690                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11691                                         if (size) {
11692                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11693                                         } else {
11694                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11695                                         }
11696                                 } else { // no literal
11697                                         if(size) {
11698                                                 pic16_emitpcode(POC_MOVFF,
11699                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11700                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11701                                         } else {
11702                                                 pic16_emitpcode(POC_MOVFF,
11703                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11704                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11705                                         }
11706                                 }
11707                         offset++;
11708                 }
11709         }
11710
11711         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11712         /* now some housekeeping stuff */
11713         if (aop) {
11714           /* we had to allocate for this iCode */
11715           pic16_freeAsmop(NULL,aop,ic,TRUE);
11716         } else { 
11717           /* we did not allocate which means left
11718            * already in a pointer register, then
11719            * if size > 0 && this could be used again
11720            * we have to point it back to where it 
11721            * belongs */
11722           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11723           if (AOP_SIZE(right) > 1
11724             && !OP_SYMBOL(result)->remat
11725             && ( OP_SYMBOL(result)->liveTo > ic->seq
11726             || ic->depth )) {
11727
11728               int size = AOP_SIZE(right) - 1;
11729
11730                 while (size--)
11731                   pic16_emitcode("decf","fsr0,f");
11732                   //pic16_emitcode("dec","%s",rname);
11733             }
11734         }
11735
11736     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11737     /* done */
11738 //release:
11739     pic16_freeAsmop(right,NULL,ic,TRUE);
11740     pic16_freeAsmop(result,NULL,ic,TRUE);
11741 }
11742
11743 /*-----------------------------------------------------------------*/
11744 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11745 /*-----------------------------------------------------------------*/
11746 static void genPagedPointerSet (operand *right,
11747                                operand *result, 
11748                                iCode *ic)
11749 {
11750     asmop *aop = NULL;
11751     regs *preg = NULL ;
11752     char *rname , *l;
11753     sym_link *retype;
11754        
11755     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11756
11757     retype= getSpec(operandType(right));
11758     
11759     pic16_aopOp(result,ic,FALSE);
11760     
11761     /* if the value is already in a pointer register
11762        then don't need anything more */
11763     if (!AOP_INPREG(AOP(result))) {
11764         /* otherwise get a free pointer register */
11765         aop = newAsmop(0);
11766         preg = getFreePtr(ic,&aop,FALSE);
11767         pic16_emitcode("mov","%s,%s",
11768                 preg->name,
11769                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11770         rname = preg->name ;
11771     } else
11772         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11773     
11774     pic16_freeAsmop(result,NULL,ic,TRUE);
11775     pic16_aopOp (right,ic,FALSE);
11776
11777     /* if bitfield then unpack the bits */
11778     if (IS_BITFIELD(retype)) 
11779         genPackBits (retype,result,right,rname,PPOINTER);
11780     else {
11781         /* we have can just get the values */
11782         int size = AOP_SIZE(right);
11783         int offset = 0 ;        
11784         
11785         while (size--) {
11786             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11787             
11788             MOVA(l);
11789             pic16_emitcode("movx","@%s,a",rname);
11790
11791             if (size)
11792                 pic16_emitcode("inc","%s",rname);
11793
11794             offset++;
11795         }
11796     }
11797     
11798     /* now some housekeeping stuff */
11799     if (aop) {
11800         /* we had to allocate for this iCode */
11801         pic16_freeAsmop(NULL,aop,ic,TRUE);
11802     } else { 
11803         /* we did not allocate which means left
11804            already in a pointer register, then
11805            if size > 0 && this could be used again
11806            we have to point it back to where it 
11807            belongs */
11808         if (AOP_SIZE(right) > 1 &&
11809             !OP_SYMBOL(result)->remat &&
11810             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11811               ic->depth )) {
11812             int size = AOP_SIZE(right) - 1;
11813             while (size--)
11814                 pic16_emitcode("dec","%s",rname);
11815         }
11816     }
11817
11818     /* done */
11819     pic16_freeAsmop(right,NULL,ic,TRUE);
11820     
11821         
11822 }
11823
11824 /*-----------------------------------------------------------------*/
11825 /* genFarPointerSet - set value from far space                     */
11826 /*-----------------------------------------------------------------*/
11827 static void genFarPointerSet (operand *right,
11828                               operand *result, iCode *ic)
11829 {
11830     int size, offset ;
11831     sym_link *retype = getSpec(operandType(right));
11832
11833     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11834     pic16_aopOp(result,ic,FALSE);
11835
11836     /* if the operand is already in dptr 
11837     then we do nothing else we move the value to dptr */
11838     if (AOP_TYPE(result) != AOP_STR) {
11839         /* if this is remateriazable */
11840         if (AOP_TYPE(result) == AOP_IMMD)
11841             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11842         else { /* we need to get it byte by byte */
11843             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11844             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11845             if (options.model == MODEL_FLAT24)
11846             {
11847                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11848             }
11849         }
11850     }
11851     /* so dptr know contains the address */
11852     pic16_freeAsmop(result,NULL,ic,TRUE);
11853     pic16_aopOp(right,ic,FALSE);
11854
11855     /* if bit then unpack */
11856     if (IS_BITFIELD(retype)) 
11857         genPackBits(retype,result,right,"dptr",FPOINTER);
11858     else {
11859         size = AOP_SIZE(right);
11860         offset = 0 ;
11861
11862         while (size--) {
11863             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11864             MOVA(l);
11865             pic16_emitcode("movx","@dptr,a");
11866             if (size)
11867                 pic16_emitcode("inc","dptr");
11868         }
11869     }
11870
11871     pic16_freeAsmop(right,NULL,ic,TRUE);
11872 }
11873
11874 /*-----------------------------------------------------------------*/
11875 /* genGenPointerSet - set value from generic pointer space         */
11876 /*-----------------------------------------------------------------*/
11877 #if 0
11878 static void genGenPointerSet (operand *right,
11879                               operand *result, iCode *ic)
11880 {
11881         int i, size, offset, lit;
11882         sym_link *retype = getSpec(operandType(right));
11883
11884         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11885
11886         pic16_aopOp(result,ic,FALSE);
11887         pic16_aopOp(right,ic,FALSE);
11888         size = AOP_SIZE(right);
11889         offset = 0;
11890
11891         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11892
11893         /* if the operand is already in dptr 
11894                 then we do nothing else we move the value to dptr */
11895         if (AOP_TYPE(result) != AOP_STR) {
11896                 /* if this is remateriazable */
11897                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11898                 // WARNING: anythig until "else" is untested!
11899                 if (AOP_TYPE(result) == AOP_IMMD) {
11900                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11901                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11902                         // load FSR0 from immediate
11903                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11904                         offset = 0;
11905                         while(size--) {
11906                                 if(size) {
11907                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11908                                 } else {
11909                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11910                                 }
11911                                 offset++;
11912                         }
11913                         goto release;
11914                 }
11915                 else { /* we need to get it byte by byte */
11916                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11917                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11918
11919                         // set up FSR0 with address of result
11920                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11921                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11922
11923                         /* hack hack! see if this the FSR. If so don't load W */
11924                         if(AOP_TYPE(right) != AOP_ACC) {
11925
11926                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11927
11928                                 if(AOP_TYPE(right) == AOP_LIT)
11929                                 {
11930                                         // copy literal
11931                                         // note: pic16_popGet handles sign extension
11932                                         for(i=0;i<size;i++) {
11933                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11934                                                 if(i < size-1)
11935                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11936                                                 else
11937                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11938                                         }
11939                                 } else {
11940                                         // copy regs
11941
11942                                         for(i=0;i<size;i++) {
11943                                                 if(i < size-1)
11944                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11945                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11946                                                 else
11947                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11948                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11949                                         }
11950                                 }
11951                                 goto release;
11952                         } 
11953                         // right = ACC
11954                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11955                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11956                         goto release;
11957         } // if (AOP_TYPE(result) != AOP_IMMD)
11958
11959         } // if (AOP_TYPE(result) != AOP_STR)
11960         /* so dptr know contains the address */
11961
11962
11963         /* if bit then unpack */
11964         if (IS_BITFIELD(retype)) 
11965                 genPackBits(retype,result,right,"dptr",GPOINTER);
11966         else {
11967                 size = AOP_SIZE(right);
11968                 offset = 0 ;
11969
11970                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11971
11972                 // set up FSR0 with address of result
11973                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11974                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11975         
11976                 while (size--) {
11977                         if (AOP_TYPE(right) == AOP_LIT) {
11978                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11979                                 if (size) {
11980                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11981                                 } else {
11982                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11983                                 }
11984                         } else { // no literal
11985                                 if(size) {
11986                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11987                                 } else {
11988                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11989                                 }
11990                         }
11991                         offset++;
11992                 }
11993         }
11994
11995         release:
11996         pic16_freeAsmop(right,NULL,ic,TRUE);
11997         pic16_freeAsmop(result,NULL,ic,TRUE);
11998 }
11999 #endif
12000
12001 static void genGenPointerSet (operand *right,
12002                               operand *result, iCode *ic)
12003 {
12004   int size;
12005   sym_link *retype = getSpec(operandType(result));
12006
12007     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12008
12009     pic16_aopOp(result,ic,FALSE);
12010     pic16_aopOp(right,ic,FALSE);
12011     size = AOP_SIZE(right);
12012
12013     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12014
12015
12016     /* if bit then unpack */
12017     if (IS_BITFIELD(retype)) {
12018 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12019       genPackBits(retype,result,right,"dptr",GPOINTER);
12020       goto release;
12021     }
12022
12023     size = AOP_SIZE(right);
12024
12025     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12026
12027
12028     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12029
12030     /* value of right+0 is placed on stack, which will be retrieved
12031      * by the support function this restoring the stack. The important
12032      * thing is that there is no need to manually restore stack pointer
12033      * here */
12034     pushaop(AOP(right), 0);
12035 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12036     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12037     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12038     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12039     
12040     /* load address to write to in WREG:FSR0H:FSR0L */
12041     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12042                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12043     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12044                                 pic16_popCopyReg(&pic16_pc_prodl)));
12045     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12046     
12047     pic16_callGenericPointerRW(1, size);
12048
12049 release:
12050     pic16_freeAsmop(right,NULL,ic,TRUE);
12051     pic16_freeAsmop(result,NULL,ic,TRUE);
12052 }
12053
12054 /*-----------------------------------------------------------------*/
12055 /* genPointerSet - stores the value into a pointer location        */
12056 /*-----------------------------------------------------------------*/
12057 static void genPointerSet (iCode *ic)
12058 {    
12059   operand *right, *result ;
12060   sym_link *type, *etype;
12061   int p_type;
12062
12063     FENTRY;
12064
12065     right = IC_RIGHT(ic);
12066     result = IC_RESULT(ic) ;
12067
12068     /* depending on the type of pointer we need to
12069     move it to the correct pointer register */
12070     type = operandType(result);
12071     etype = getSpec(type);
12072     
12073     /* if left is of type of pointer then it is simple */
12074     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12075         p_type = DCL_TYPE(type);
12076     }
12077     else {
12078         /* we have to go by the storage class */
12079         p_type = PTR_TYPE(SPEC_OCLS(etype));
12080
12081 /*      if (SPEC_OCLS(etype)->codesp ) { */
12082 /*          p_type = CPOINTER ;  */
12083 /*      } */
12084 /*      else */
12085 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12086 /*              p_type = FPOINTER ; */
12087 /*          else */
12088 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12089 /*                  p_type = PPOINTER ; */
12090 /*              else */
12091 /*                  if (SPEC_OCLS(etype) == idata ) */
12092 /*                      p_type = IPOINTER ; */
12093 /*                  else */
12094 /*                      p_type = POINTER ; */
12095     }
12096
12097     /* now that we have the pointer type we assign
12098     the pointer values */
12099     switch (p_type) {
12100       case POINTER:
12101       case IPOINTER:
12102         genNearPointerSet (right,result,ic);
12103         break;
12104
12105       case PPOINTER:
12106         genPagedPointerSet (right,result,ic);
12107         break;
12108
12109       case FPOINTER:
12110         genFarPointerSet (right,result,ic);
12111         break;
12112         
12113       case GPOINTER:
12114         genGenPointerSet (right,result,ic);
12115         break;
12116
12117       default:
12118         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12119           "genPointerSet: illegal pointer type");
12120     }
12121 }
12122
12123 /*-----------------------------------------------------------------*/
12124 /* genIfx - generate code for Ifx statement                        */
12125 /*-----------------------------------------------------------------*/
12126 static void genIfx (iCode *ic, iCode *popIc)
12127 {
12128   operand *cond = IC_COND(ic);
12129   int isbit =0;
12130
12131     FENTRY;
12132
12133     pic16_aopOp(cond,ic,FALSE);
12134
12135     /* get the value into acc */
12136     if (AOP_TYPE(cond) != AOP_CRY)
12137       pic16_toBoolean(cond);
12138     else
12139       isbit = 1;
12140     /* the result is now in the accumulator */
12141     pic16_freeAsmop(cond,NULL,ic,TRUE);
12142
12143     /* if there was something to be popped then do it */
12144     if (popIc)
12145       genIpop(popIc);
12146
12147     /* if the condition is  a bit variable */
12148     if (isbit && IS_ITEMP(cond) && 
12149         SPIL_LOC(cond)) {
12150       genIfxJump(ic,"c");
12151       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12152     } else {
12153       if (isbit && !IS_ITEMP(cond))
12154         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12155         else
12156         genIfxJump(ic,"a");
12157     }
12158     ic->generated = 1;
12159 }
12160
12161 /*-----------------------------------------------------------------*/
12162 /* genAddrOf - generates code for address of                       */
12163 /*-----------------------------------------------------------------*/
12164 static void genAddrOf (iCode *ic)
12165 {
12166   operand *result, *left;
12167   int size;
12168   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12169   pCodeOp *pcop0, *pcop1, *pcop2;
12170
12171     FENTRY;
12172
12173     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12174
12175     sym = OP_SYMBOL( IC_LEFT(ic) );
12176     
12177     if(sym->onStack) {
12178       /* get address of symbol on stack */
12179       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12180 #if 0
12181       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12182                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12183 #endif
12184
12185       // operands on stack are accessible via "FSR2 + index" with index
12186       // starting at 2 for arguments and growing from 0 downwards for
12187       // local variables (index == 0 is not assigned so we add one here)
12188       {
12189         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12190         if (soffs <= 0) {
12191           assert (soffs < 0);
12192           soffs++;
12193         } // if
12194         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12195         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12196         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12197         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12198         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12199         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12200         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12201       }
12202
12203       goto release;
12204     }
12205         
12206 //      if(pic16_debug_verbose) {
12207 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12208 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12209 //      }
12210         
12211     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12212     size = AOP_SIZE(IC_RESULT(ic));
12213
12214     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12215     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12216     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12217         
12218     if (size == 3) {
12219       pic16_emitpcode(POC_MOVLW, pcop0);
12220       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12221       pic16_emitpcode(POC_MOVLW, pcop1);
12222       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12223       pic16_emitpcode(POC_MOVLW, pcop2);
12224       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12225     } else
12226     if (size == 2) {
12227       pic16_emitpcode(POC_MOVLW, pcop0);
12228       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12229       pic16_emitpcode(POC_MOVLW, pcop1);
12230     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12231     } else {
12232       pic16_emitpcode(POC_MOVLW, pcop0);
12233       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12234     }
12235
12236     pic16_freeAsmop(left, NULL, ic, FALSE);
12237 release:
12238     pic16_freeAsmop(result,NULL,ic,TRUE);
12239 }
12240
12241
12242 #if 0
12243 /*-----------------------------------------------------------------*/
12244 /* genFarFarAssign - assignment when both are in far space         */
12245 /*-----------------------------------------------------------------*/
12246 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12247 {
12248     int size = AOP_SIZE(right);
12249     int offset = 0;
12250     char *l ;
12251     /* first push the right side on to the stack */
12252     while (size--) {
12253         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12254         MOVA(l);
12255         pic16_emitcode ("push","acc");
12256     }
12257     
12258     pic16_freeAsmop(right,NULL,ic,FALSE);
12259     /* now assign DPTR to result */
12260     pic16_aopOp(result,ic,FALSE);
12261     size = AOP_SIZE(result);
12262     while (size--) {
12263         pic16_emitcode ("pop","acc");
12264         pic16_aopPut(AOP(result),"a",--offset);
12265     }
12266     pic16_freeAsmop(result,NULL,ic,FALSE);
12267         
12268 }
12269 #endif
12270
12271 /*-----------------------------------------------------------------*/
12272 /* genAssign - generate code for assignment                        */
12273 /*-----------------------------------------------------------------*/
12274 static void genAssign (iCode *ic)
12275 {
12276   operand *result, *right;
12277   int size, offset,know_W;
12278   unsigned long lit = 0L;
12279
12280   result = IC_RESULT(ic);
12281   right  = IC_RIGHT(ic) ;
12282
12283   FENTRY;
12284   
12285   /* if they are the same */
12286   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12287     return ;
12288
12289   /* reversed order operands are aopOp'ed so that result operand
12290    * is effective in case right is a stack symbol. This maneauver
12291    * allows to use the _G.resDirect flag later */
12292   pic16_aopOp(result,ic,TRUE);
12293   pic16_aopOp(right,ic,FALSE);
12294
12295   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12296
12297   /* if they are the same registers */
12298   if (pic16_sameRegs(AOP(right),AOP(result)))
12299     goto release;
12300
12301   /* if the result is a bit */
12302   if (AOP_TYPE(result) == AOP_CRY) {
12303     /* if the right size is a literal then
12304        we know what the value is */
12305     if (AOP_TYPE(right) == AOP_LIT) {
12306           
12307       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12308                   pic16_popGet(AOP(result),0));
12309
12310       if (((int) operandLitValue(right))) 
12311         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12312                        AOP(result)->aopu.aop_dir,
12313                        AOP(result)->aopu.aop_dir);
12314       else
12315         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12316                        AOP(result)->aopu.aop_dir,
12317                        AOP(result)->aopu.aop_dir);
12318       goto release;
12319     }
12320
12321     /* the right is also a bit variable */
12322     if (AOP_TYPE(right) == AOP_CRY) {
12323       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12324       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12325       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12326
12327       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12328                      AOP(result)->aopu.aop_dir,
12329                      AOP(result)->aopu.aop_dir);
12330       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12331                      AOP(right)->aopu.aop_dir,
12332                      AOP(right)->aopu.aop_dir);
12333       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12334                      AOP(result)->aopu.aop_dir,
12335                      AOP(result)->aopu.aop_dir);
12336       goto release ;
12337     }
12338
12339     /* we need to or */
12340     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12341     pic16_toBoolean(right);
12342     emitSKPZ;
12343     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12344     //pic16_aopPut(AOP(result),"a",0);
12345     goto release ;
12346   }
12347
12348   /* bit variables done */
12349   /* general case */
12350   size = AOP_SIZE(result);
12351   offset = 0 ;
12352
12353   if(AOP_TYPE(right) == AOP_LIT) {
12354         if(!IS_FLOAT(operandType( right )))
12355                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12356         else {
12357            union {
12358               unsigned long lit_int;
12359               float lit_float;
12360             } info;
12361         
12362                 /* take care if literal is a float */
12363                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12364                 lit = info.lit_int;
12365         }
12366   }
12367
12368 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12369 //                      sizeof(unsigned long int), sizeof(float));
12370
12371
12372   if (AOP_TYPE(right) == AOP_REG) {
12373     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12374     while (size--) {
12375       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12376     } // while
12377     goto release;
12378   }
12379
12380   /* when do we have to read the program memory?
12381    * - if right itself is a symbol in code space
12382    *   (we don't care what it points to if it's a pointer)
12383    * - AND right is not a function (we would want its address)
12384    */
12385   if(AOP_TYPE(right) != AOP_LIT
12386         && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12387         && !IS_FUNC(OP_SYM_TYPE(right))
12388         && !IS_ITEMP(right))
12389   {
12390         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12391         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12392
12393         // set up table pointer
12394         if(is_LitOp(right)) {
12395 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12396                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12397                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12398                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12399                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12400                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12401                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12402         } else {
12403 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12404                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12405                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12406                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12407                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12408                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12409                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12410         }
12411
12412         /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12413         size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12414         while(size--) {
12415                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12416                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12417                         pic16_popGet(AOP(result),offset)));
12418                 offset++;
12419         }
12420
12421         /* FIXME: for pointers we need to extend differently (according
12422          * to pointer type DATA/CODE/EEPROM/... :*/
12423         size = getSize(OP_SYM_TYPE(right));
12424         if(AOP_SIZE(result) > size) {
12425                 size = AOP_SIZE(result) - size;
12426                 while(size--) {
12427                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12428                         offset++;
12429                 }
12430         }
12431         goto release;
12432   }
12433
12434
12435
12436 #if 0
12437 /* VR - What is this?! */
12438   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12439     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12440     if(aopIdx(AOP(result),0) == 4) {
12441
12442       /* this is a workaround to save value of right into wreg too,
12443        * value of wreg is going to be used later */
12444       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12445       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12446       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12447       goto release;
12448     } else
12449 //      assert(0);
12450       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12451   }
12452 #endif
12453
12454   know_W=-1;
12455   while (size--) {
12456   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12457     if(AOP_TYPE(right) == AOP_LIT) {
12458       if(lit&0xff) {
12459         if(know_W != (lit&0xff))
12460           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12461         know_W = lit&0xff;
12462         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12463       } else
12464         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12465
12466       lit >>= 8;
12467
12468     } else if (AOP_TYPE(right) == AOP_CRY) {
12469       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12470       if(offset == 0) {
12471         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12472         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12473         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12474       }
12475     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12476         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12477         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12478     } else {
12479       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12480
12481       if(!_G.resDirect)         /* use this aopForSym feature */
12482         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12483     }
12484             
12485     offset++;
12486   }
12487   
12488  release:
12489   pic16_freeAsmop (right,NULL,ic,FALSE);
12490   pic16_freeAsmop (result,NULL,ic,TRUE);
12491 }   
12492
12493 /*-----------------------------------------------------------------*/
12494 /* genJumpTab - generates code for jump table                       */
12495 /*-----------------------------------------------------------------*/
12496 static void genJumpTab (iCode *ic)
12497 {
12498   symbol *jtab;
12499   char *l;
12500   pCodeOp *jt_offs;
12501   pCodeOp *jt_offs_hi;
12502   pCodeOp *jt_label;
12503
12504     FENTRY;
12505
12506     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12507     /* get the condition into accumulator */
12508     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12509     MOVA(l);
12510     /* multiply by three */
12511     pic16_emitcode("add","a,acc");
12512     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12513
12514     jtab = newiTempLabel(NULL);
12515     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12516     pic16_emitcode("jmp","@a+dptr");
12517     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12518
12519 #if 0
12520     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12521     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12522     emitSKPNC;
12523     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12524     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12525     pic16_emitpLabel(jtab->key);
12526
12527 #else
12528
12529     jt_offs = pic16_popGetTempReg(0);
12530     jt_offs_hi = pic16_popGetTempReg(1);
12531     jt_label = pic16_popGetLabel (jtab->key);
12532     //fprintf (stderr, "Creating jump table...\n");
12533
12534     // calculate offset into jump table (idx * sizeof (GOTO))
12535     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12536     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12537     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12538     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12539     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12540     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12541     pic16_emitpcode(POC_MOVWF , jt_offs);
12542
12543     // prepare PCLATx (set to first entry in jump table)
12544     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12545     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12546     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12547     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12548     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12549
12550     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12551     pic16_emitpcode(POC_ADDWF , jt_offs);
12552     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12553     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12554     emitSKPNC;
12555     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12556
12557     // release temporaries and prepare jump into table (new PCL --> WREG)
12558     pic16_emitpcode(POC_MOVFW , jt_offs);
12559     pic16_popReleaseTempReg (jt_offs_hi, 1);
12560     pic16_popReleaseTempReg (jt_offs, 0);
12561
12562     // jump into the table
12563     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12564
12565     pic16_emitpLabelFORCE(jtab->key);
12566 #endif
12567
12568     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12569 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12570
12571     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12572     /* now generate the jump labels */
12573     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12574          jtab = setNextItem(IC_JTLABELS(ic))) {
12575 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12576         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12577         
12578     }
12579     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12580
12581 }
12582
12583 /*-----------------------------------------------------------------*/
12584 /* genMixedOperation - gen code for operators between mixed types  */
12585 /*-----------------------------------------------------------------*/
12586 /*
12587   TSD - Written for the PIC port - but this unfortunately is buggy.
12588   This routine is good in that it is able to efficiently promote 
12589   types to different (larger) sizes. Unfortunately, the temporary
12590   variables that are optimized out by this routine are sometimes
12591   used in other places. So until I know how to really parse the 
12592   iCode tree, I'm going to not be using this routine :(.
12593 */
12594 static int genMixedOperation (iCode *ic)
12595 {
12596 #if 0
12597   operand *result = IC_RESULT(ic);
12598   sym_link *ctype = operandType(IC_LEFT(ic));
12599   operand *right = IC_RIGHT(ic);
12600   int ret = 0;
12601   int big,small;
12602   int offset;
12603
12604   iCode *nextic;
12605   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12606
12607   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12608
12609   nextic = ic->next;
12610   if(!nextic)
12611     return 0;
12612
12613   nextright = IC_RIGHT(nextic);
12614   nextleft  = IC_LEFT(nextic);
12615   nextresult = IC_RESULT(nextic);
12616
12617   pic16_aopOp(right,ic,FALSE);
12618   pic16_aopOp(result,ic,FALSE);
12619   pic16_aopOp(nextright,  nextic, FALSE);
12620   pic16_aopOp(nextleft,   nextic, FALSE);
12621   pic16_aopOp(nextresult, nextic, FALSE);
12622
12623   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12624
12625     operand *t = right;
12626     right = nextright;
12627     nextright = t; 
12628
12629     pic16_emitcode(";remove right +","");
12630
12631   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12632 /*
12633     operand *t = right;
12634     right = nextleft;
12635     nextleft = t; 
12636 */
12637     pic16_emitcode(";remove left +","");
12638   } else
12639     return 0;
12640
12641   big = AOP_SIZE(nextleft);
12642   small = AOP_SIZE(nextright);
12643
12644   switch(nextic->op) {
12645
12646   case '+':
12647     pic16_emitcode(";optimize a +","");
12648     /* if unsigned or not an integral type */
12649     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12650       pic16_emitcode(";add a bit to something","");
12651     } else {
12652
12653       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12654
12655       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12656         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12657         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12658       } else
12659         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12660
12661       offset = 0;
12662       while(--big) {
12663
12664         offset++;
12665
12666         if(--small) {
12667           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12668             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12669             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12670           }
12671
12672           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12673           emitSKPNC;
12674           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12675                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12676                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12677           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12678           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12679
12680         } else {
12681           pic16_emitcode("rlf","known_zero,w");
12682
12683           /*
12684             if right is signed
12685               btfsc  right,7
12686                addlw ff
12687           */
12688           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12689             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12690             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12691           } else {
12692             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12693           }
12694         }
12695       }
12696       ret = 1;
12697     }
12698   }
12699   ret = 1;
12700
12701 release:
12702   pic16_freeAsmop(right,NULL,ic,TRUE);
12703   pic16_freeAsmop(result,NULL,ic,TRUE);
12704   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12705   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12706   if(ret)
12707     nextic->generated = 1;
12708
12709   return ret;
12710 #else
12711   return 0;
12712 #endif
12713 }
12714 /*-----------------------------------------------------------------*/
12715 /* genCast - gen code for casting                                  */
12716 /*-----------------------------------------------------------------*/
12717 static void genCast (iCode *ic)
12718 {
12719   operand *result = IC_RESULT(ic);
12720   sym_link *ctype = operandType(IC_LEFT(ic));
12721   sym_link *rtype = operandType(IC_RIGHT(ic));
12722   sym_link *restype = operandType(IC_RESULT(ic));
12723   operand *right = IC_RIGHT(ic);
12724   int size, offset ;
12725
12726
12727     FENTRY;
12728
12729         /* if they are equivalent then do nothing */
12730 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12731 //              return ;
12732
12733         pic16_aopOp(result,ic,FALSE);
12734         pic16_aopOp(right,ic,FALSE) ;
12735
12736         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12737
12738
12739         /* if the result is a bit */
12740         if (AOP_TYPE(result) == AOP_CRY) {
12741         
12742                 /* if the right size is a literal then
12743                  * we know what the value is */
12744                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12745
12746                 if (AOP_TYPE(right) == AOP_LIT) {
12747                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12748                                 pic16_popGet(AOP(result),0));
12749
12750                         if (((int) operandLitValue(right))) 
12751                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12752                                         AOP(result)->aopu.aop_dir,
12753                                         AOP(result)->aopu.aop_dir);
12754                         else
12755                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12756                                         AOP(result)->aopu.aop_dir,
12757                                         AOP(result)->aopu.aop_dir);
12758                         goto release;
12759                 }
12760
12761                 /* the right is also a bit variable */
12762                 if (AOP_TYPE(right) == AOP_CRY) {
12763                         emitCLRC;
12764                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12765
12766                         pic16_emitcode("clrc","");
12767                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12768                                 AOP(right)->aopu.aop_dir,
12769                                 AOP(right)->aopu.aop_dir);
12770                         pic16_aopPut(AOP(result),"c",0);
12771                         goto release ;
12772                 }
12773
12774                 /* we need to or */
12775                 if (AOP_TYPE(right) == AOP_REG) {
12776                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12777                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12778                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12779                 }
12780                 pic16_toBoolean(right);
12781                 pic16_aopPut(AOP(result),"a",0);
12782                 goto release ;
12783         }
12784
12785         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12786           int offset = 1;
12787
12788                 size = AOP_SIZE(result);
12789
12790                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12791
12792                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12793                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12794                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12795
12796                 while (size--)
12797                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12798
12799                 goto release;
12800         }
12801
12802         if(IS_BITFIELD(getSpec(restype))
12803           && IS_BITFIELD(getSpec(rtype))) {
12804           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12805         }
12806
12807         /* if they are the same size : or less */
12808         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12809
12810                 /* if they are in the same place */
12811                 if (pic16_sameRegs(AOP(right),AOP(result)))
12812                         goto release;
12813
12814                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12815 #if 0
12816                 if (IS_PTR_CONST(rtype))
12817 #else
12818                 if (IS_CODEPTR(rtype))
12819 #endif
12820                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12821
12822 #if 0
12823                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12824 #else
12825                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12826 #endif
12827                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12828
12829 #if 0
12830                 if(AOP_TYPE(right) == AOP_IMMD) {
12831                   pCodeOp *pcop0, *pcop1, *pcop2;
12832                   symbol *sym = OP_SYMBOL( right );
12833
12834                         size = AOP_SIZE(result);
12835                         /* low */
12836                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12837                         /* high */
12838                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12839                         /* upper */
12840                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12841         
12842                         if (size == 3) {
12843                                 pic16_emitpcode(POC_MOVLW, pcop0);
12844                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12845                                 pic16_emitpcode(POC_MOVLW, pcop1);
12846                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12847                                 pic16_emitpcode(POC_MOVLW, pcop2);
12848                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12849                         } else
12850                         if (size == 2) {
12851                                 pic16_emitpcode(POC_MOVLW, pcop0);
12852                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12853                                 pic16_emitpcode(POC_MOVLW, pcop1);
12854                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12855                         } else {
12856                                 pic16_emitpcode(POC_MOVLW, pcop0);
12857                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12858                         }
12859                 } else
12860 #endif
12861                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12862                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12863                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12864                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12865                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12866                         if(AOP_SIZE(result) <2)
12867                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12868                 } else {
12869                         /* if they in different places then copy */
12870                         size = AOP_SIZE(result);
12871                         offset = 0 ;
12872                         while (size--) {
12873                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12874                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12875                                 offset++;
12876                         }
12877                 }
12878                 goto release;
12879         }
12880
12881         /* if the result is of type pointer */
12882         if (IS_PTR(ctype)) {
12883           int p_type;
12884           sym_link *type = operandType(right);
12885           sym_link *etype = getSpec(type);
12886
12887                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
12888
12889                 /* pointer to generic pointer */
12890                 if (IS_GENPTR(ctype)) {
12891                   char *l = zero;
12892             
12893                         if (IS_PTR(type)) 
12894                                 p_type = DCL_TYPE(type);
12895                         else {
12896                 /* we have to go by the storage class */
12897                 p_type = PTR_TYPE(SPEC_OCLS(etype));
12898
12899 /*              if (SPEC_OCLS(etype)->codesp )  */
12900 /*                  p_type = CPOINTER ;  */
12901 /*              else */
12902 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12903 /*                      p_type = FPOINTER ; */
12904 /*                  else */
12905 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12906 /*                          p_type = PPOINTER; */
12907 /*                      else */
12908 /*                          if (SPEC_OCLS(etype) == idata ) */
12909 /*                              p_type = IPOINTER ; */
12910 /*                          else */
12911 /*                              p_type = POINTER ; */
12912             }
12913                 
12914             /* the first two bytes are known */
12915       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
12916             size = GPTRSIZE - 1; 
12917             offset = 0 ;
12918             while (size--) {
12919               if(offset < AOP_SIZE(right)) {
12920                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12921                 pic16_mov2f(AOP(result), AOP(right), offset);
12922 /*
12923                 if ((AOP_TYPE(right) == AOP_PCODE) && 
12924                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12925                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12926                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12927                 } else { 
12928                   
12929                   pic16_aopPut(AOP(result),
12930                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12931                          offset);
12932                 }
12933 */
12934               } else 
12935                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12936               offset++;
12937             }
12938             /* the last byte depending on type */
12939             switch (p_type) {
12940             case IPOINTER:
12941             case POINTER:
12942                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12943                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12944 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
12945                 break;
12946
12947             case CPOINTER:
12948                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12949                 break;
12950
12951             case FPOINTER:
12952               pic16_emitcode(";BUG!? ","%d",__LINE__);
12953                 l = one;
12954                 break;
12955             case PPOINTER:
12956               pic16_emitcode(";BUG!? ","%d",__LINE__);
12957                 l = "#0x03";
12958                 break;
12959
12960             case GPOINTER:
12961                 if (GPTRSIZE > AOP_SIZE(right)) {
12962                   // assume data pointer... THIS MIGHT BE WRONG!
12963                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12964                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12965                 } else {
12966                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12967                 }
12968               break;
12969               
12970             default:
12971                 /* this should never happen */
12972                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
12973                        "got unknown pointer type");
12974                 exit(1);
12975             }
12976             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
12977             goto release ;
12978         }
12979         
12980         
12981         assert( 0 );
12982         /* just copy the pointers */
12983         size = AOP_SIZE(result);
12984         offset = 0 ;
12985         while (size--) {
12986             pic16_aopPut(AOP(result),
12987                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12988                    offset);
12989             offset++;
12990         }
12991         goto release ;
12992     }
12993     
12994
12995
12996     /* so we now know that the size of destination is greater
12997     than the size of the source.
12998     Now, if the next iCode is an operator then we might be
12999     able to optimize the operation without performing a cast.
13000     */
13001     if(genMixedOperation(ic))
13002       goto release;
13003
13004     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13005     
13006     /* we move to result for the size of source */
13007     size = AOP_SIZE(right);
13008     offset = 0 ;
13009
13010     while (size--) {
13011       if(!_G.resDirect)
13012         pic16_mov2f(AOP(result), AOP(right), offset);
13013       offset++;
13014     }
13015
13016     /* now depending on the sign of the destination */
13017     size = AOP_SIZE(result) - AOP_SIZE(right);
13018     /* if unsigned or not an integral type */
13019     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13020       while (size--)
13021         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13022     } else {
13023       /* we need to extend the sign :( */
13024
13025       if(size == 1) {
13026         /* Save one instruction of casting char to int */
13027         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13028         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13029         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13030       } else {
13031         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13032
13033         if(offset)
13034           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13035         else
13036           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13037         
13038         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13039
13040         while (size--)
13041           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13042       }
13043     }
13044
13045 release:
13046     pic16_freeAsmop(right,NULL,ic,TRUE);
13047     pic16_freeAsmop(result,NULL,ic,TRUE);
13048
13049 }
13050
13051 /*-----------------------------------------------------------------*/
13052 /* genDjnz - generate decrement & jump if not zero instrucion      */
13053 /*-----------------------------------------------------------------*/
13054 static int genDjnz (iCode *ic, iCode *ifx)
13055 {
13056     symbol *lbl, *lbl1;
13057     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13058
13059     if (!ifx)
13060         return 0;
13061     
13062     /* if the if condition has a false label
13063        then we cannot save */
13064     if (IC_FALSE(ifx))
13065         return 0;
13066
13067     /* if the minus is not of the form 
13068        a = a - 1 */
13069     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13070         !IS_OP_LITERAL(IC_RIGHT(ic)))
13071         return 0;
13072
13073     if (operandLitValue(IC_RIGHT(ic)) != 1)
13074         return 0;
13075
13076     /* if the size of this greater than one then no
13077        saving */
13078     if (getSize(operandType(IC_RESULT(ic))) > 1)
13079         return 0;
13080
13081     /* otherwise we can save BIG */
13082     lbl = newiTempLabel(NULL);
13083     lbl1= newiTempLabel(NULL);
13084
13085     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13086     
13087     if (IS_AOP_PREG(IC_RESULT(ic))) {
13088         pic16_emitcode("dec","%s",
13089                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13090         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13091         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13092     } else {    
13093
13094
13095       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13096       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13097
13098       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13099       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13100
13101     }
13102     
13103     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13104     ifx->generated = 1;
13105     return 1;
13106 }
13107
13108 /*-----------------------------------------------------------------*/
13109 /* genReceive - generate code for a receive iCode                  */
13110 /*-----------------------------------------------------------------*/
13111 static void genReceive (iCode *ic)
13112 {    
13113
13114   FENTRY;
13115
13116 #if 0
13117   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13118         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13119 #endif
13120 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13121
13122   if (isOperandInFarSpace(IC_RESULT(ic))
13123       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13124           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13125
13126     int size = getSize(operandType(IC_RESULT(ic)));
13127     int offset =  pic16_fReturnSizePic - size;
13128
13129       assert( 0 );
13130       while (size--) {
13131         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13132                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13133                       offset++;
13134         }
13135
13136       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13137
13138       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13139       size = AOP_SIZE(IC_RESULT(ic));
13140       offset = 0;
13141       while (size--) {
13142         pic16_emitcode ("pop","acc");
13143         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13144       }
13145   } else {
13146     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13147     _G.accInUse++;
13148     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13149     _G.accInUse--;
13150
13151     /* set pseudo stack pointer to where it should be - dw*/
13152     GpsuedoStkPtr = ic->parmBytes;
13153
13154     /* setting GpsuedoStkPtr has side effects here: */
13155     assignResultValue(IC_RESULT(ic), 0);
13156   }
13157
13158   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13159 }
13160
13161 /*-----------------------------------------------------------------*/
13162 /* genDummyRead - generate code for dummy read of volatiles        */
13163 /*-----------------------------------------------------------------*/
13164 static void
13165 genDummyRead (iCode * ic)
13166 {
13167   operand *op;
13168   int i;
13169
13170   op = IC_RIGHT(ic);
13171   if (op && IS_SYMOP(op)) {
13172     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13173       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13174       return;
13175     }
13176     pic16_aopOp (op, ic, FALSE);
13177     for (i=0; i < AOP_SIZE(op); i++) {
13178       // may need to protect this from the peepholer -- this is not nice but works...
13179       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13180       pic16_mov2w (AOP(op),i);
13181       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13182     } // for i
13183     pic16_freeAsmop (op, NULL, ic, TRUE);
13184   } else if (op) {
13185     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13186   } // if
13187 }
13188
13189 /*-----------------------------------------------------------------*/
13190 /* genpic16Code - generate code for pic16 based controllers        */
13191 /*-----------------------------------------------------------------*/
13192 /*
13193  * At this point, ralloc.c has gone through the iCode and attempted
13194  * to optimize in a way suitable for a PIC. Now we've got to generate
13195  * PIC instructions that correspond to the iCode.
13196  *
13197  * Once the instructions are generated, we'll pass through both the
13198  * peep hole optimizer and the pCode optimizer.
13199  *-----------------------------------------------------------------*/
13200
13201 void genpic16Code (iCode *lic)
13202 {
13203   iCode *ic;
13204   int cln = 0;
13205
13206     lineHead = lineCurr = NULL;
13207
13208     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13209     pic16_addpBlock(pb);
13210
13211 #if 0
13212     /* if debug information required */
13213     if (options.debug && currFunc) {
13214       if (currFunc) {
13215         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13216       }
13217     }
13218 #endif
13219
13220     for (ic = lic ; ic ; ic = ic->next ) {
13221
13222       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13223       if ( cln != ic->lineno ) {
13224         if ( options.debug ) {
13225           debugFile->writeCLine (ic);
13226         }
13227         
13228         if(!options.noCcodeInAsm) {
13229           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13230               printCLine(ic->filename, ic->lineno)));
13231         }
13232
13233         cln = ic->lineno ;
13234       }
13235         
13236       if(options.iCodeInAsm) {
13237         char *l;
13238
13239           /* insert here code to print iCode as comment */
13240           l = Safe_strdup(printILine(ic));
13241           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13242       }
13243         
13244       /* if the result is marked as
13245        * spilt and rematerializable or code for
13246        * this has already been generated then
13247        * do nothing */
13248       if (resultRemat(ic) || ic->generated ) 
13249         continue ;
13250         
13251       /* depending on the operation */
13252       switch (ic->op) {
13253         case '!' :
13254           pic16_genNot(ic);
13255           break;
13256             
13257         case '~' :
13258           pic16_genCpl(ic);
13259           break;
13260             
13261         case UNARYMINUS:
13262           genUminus (ic);
13263           break;
13264             
13265         case IPUSH:
13266           genIpush (ic);
13267           break;
13268             
13269         case IPOP:
13270           /* IPOP happens only when trying to restore a 
13271            * spilt live range, if there is an ifx statement
13272            * following this pop then the if statement might
13273            * be using some of the registers being popped which
13274            * would destroy the contents of the register so
13275            * we need to check for this condition and handle it */
13276            if (ic->next
13277              && ic->next->op == IFX
13278              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13279                genIfx (ic->next,ic);
13280           else
13281             genIpop (ic);
13282           break; 
13283             
13284         case CALL:
13285           genCall (ic);
13286           break;
13287             
13288         case PCALL:
13289           genPcall (ic);
13290           break;
13291             
13292         case FUNCTION:
13293           genFunction (ic);
13294           break;
13295             
13296         case ENDFUNCTION:
13297           genEndFunction (ic);
13298           break;
13299             
13300         case RETURN:
13301           genRet (ic);
13302           break;
13303             
13304         case LABEL:
13305           genLabel (ic);
13306           break;
13307             
13308         case GOTO:
13309           genGoto (ic);
13310           break;
13311             
13312         case '+' :
13313           pic16_genPlus (ic) ;
13314           break;
13315             
13316         case '-' :
13317           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13318             pic16_genMinus (ic);
13319           break;
13320
13321         case '*' :
13322           genMult (ic);
13323           break;
13324             
13325         case '/' :
13326           genDiv (ic) ;
13327           break;
13328             
13329         case '%' :
13330           genMod (ic);
13331           break;
13332             
13333         case '>' :
13334           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13335           break;
13336             
13337         case '<' :
13338           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13339           break;
13340             
13341         case LE_OP:
13342         case GE_OP:
13343         case NE_OP:
13344           /* note these two are xlated by algebraic equivalence
13345            * during parsing SDCC.y */
13346           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13347             "got '>=' or '<=' shouldn't have come here");
13348           break;
13349
13350         case EQ_OP:
13351           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13352           break;            
13353             
13354         case AND_OP:
13355           genAndOp (ic);
13356           break;
13357             
13358         case OR_OP:
13359           genOrOp (ic);
13360           break;
13361             
13362         case '^' :
13363           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13364           break;
13365             
13366         case '|' :
13367           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13368           break;
13369             
13370         case BITWISEAND:
13371           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13372           break;
13373             
13374         case INLINEASM:
13375           genInline (ic);
13376           break;
13377             
13378         case RRC:
13379           genRRC (ic);
13380           break;
13381             
13382         case RLC:
13383           genRLC (ic);
13384           break;
13385             
13386         case GETHBIT:
13387           genGetHbit (ic);
13388           break;
13389             
13390         case LEFT_OP:
13391           genLeftShift (ic);
13392           break;
13393             
13394         case RIGHT_OP:
13395           genRightShift (ic);
13396           break;
13397             
13398         case GET_VALUE_AT_ADDRESS:
13399           genPointerGet(ic);
13400           break;
13401             
13402         case '=' :
13403           if (POINTER_SET(ic))
13404             genPointerSet(ic);
13405           else
13406             genAssign(ic);
13407           break;
13408             
13409         case IFX:
13410           genIfx (ic,NULL);
13411           break;
13412             
13413         case ADDRESS_OF:
13414           genAddrOf (ic);
13415           break;
13416             
13417         case JUMPTABLE:
13418           genJumpTab (ic);
13419           break;
13420             
13421         case CAST:
13422           genCast (ic);
13423           break;
13424             
13425         case RECEIVE:
13426           genReceive(ic);
13427           break;
13428             
13429         case SEND:
13430           addSet(&_G.sendSet,ic);
13431           break;
13432
13433         case DUMMY_READ_VOLATILE:
13434           genDummyRead (ic);
13435           break;
13436
13437         default :
13438           ic = ic;
13439       }
13440     }
13441
13442
13443     /* now we are ready to call the
13444        peep hole optimizer */
13445     if (!options.nopeep)
13446       peepHole (&lineHead);
13447
13448     /* now do the actual printing */
13449     printLine (lineHead, codeOutFile);
13450
13451 #ifdef PCODE_DEBUG
13452     DFPRINTF((stderr,"printing pBlock\n\n"));
13453     pic16_printpBlock(stdout,pb);
13454 #endif
13455
13456     return;
13457 }
13458