* device/include/pic16/pic18f1220.h,
[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     unsigned 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     unsigned 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     unsigned 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 /* genUminusFloat - unary minus for floating points                */
2683 /*-----------------------------------------------------------------*/
2684 static void genUminusFloat(operand *op,operand *result)
2685 {
2686   int size ,offset =0 ;
2687   
2688     FENTRY;
2689     /* for this we just need to flip the 
2690     first it then copy the rest in place */
2691     size = AOP_SIZE(op);
2692     assert( size == AOP_SIZE(result) );
2693
2694     while(size--) {
2695       pic16_mov2f(AOP(result), AOP(op), offset);
2696       offset++;
2697     }
2698     
2699     /* toggle the MSB's highest bit */
2700     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2701 }
2702
2703 /*-----------------------------------------------------------------*/
2704 /* genUminus - unary minus code generation                         */
2705 /*-----------------------------------------------------------------*/
2706 static void genUminus (iCode *ic)
2707 {
2708   int size, i;
2709   sym_link *optype, *rtype;
2710   symbol *label;
2711   int needLabel=0;
2712
2713     FENTRY;     
2714     
2715     /* assign asmops */
2716     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2717     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2718
2719     /* if both in bit space then special case */
2720     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2721       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2722         
2723         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2724         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2725         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2726         goto release; 
2727     } 
2728
2729     optype = operandType(IC_LEFT(ic));
2730     rtype = operandType(IC_RESULT(ic));
2731
2732
2733     /* if float then do float stuff */
2734     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2735       if(IS_FIXED(optype))
2736         debugf("implement fixed16x16 type\n", 0);
2737         
2738         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2739         goto release;
2740     }
2741
2742     /* otherwise subtract from zero by taking the 2's complement */
2743     size = AOP_SIZE(IC_LEFT(ic));
2744     assert( size == AOP_SIZE(IC_RESULT(ic)) );
2745     label = newiTempLabel ( NULL );
2746     
2747     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2748       for (i=size-1; i > 0; i--) {
2749         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2750       } // for
2751       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2752       for (i=1; i < size; i++) {
2753         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2754         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2755       } // for
2756     } else {
2757       for (i=size-1; i >= 0; i--) {
2758         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2759         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2760       } // for
2761       if (size > 1) {
2762         for (i=0; i < size-2; i++) {
2763           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2764           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2765         } // for
2766         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2767       } // if
2768       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2769     }
2770     if (needLabel)
2771       pic16_emitpLabel (label->key);
2772
2773 release:
2774     /* release the aops */
2775     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2776     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2777 }
2778
2779 #if 0
2780 /*-----------------------------------------------------------------*/
2781 /* saveRegisters - will look for a call and save the registers     */
2782 /*-----------------------------------------------------------------*/
2783 static void saveRegisters(iCode *lic) 
2784 {
2785     int i;
2786     iCode *ic;
2787     bitVect *rsave;
2788     sym_link *dtype;
2789
2790     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2791     /* look for call */
2792     for (ic = lic ; ic ; ic = ic->next) 
2793         if (ic->op == CALL || ic->op == PCALL)
2794             break;
2795
2796     if (!ic) {
2797         fprintf(stderr,"found parameter push with no function call\n");
2798         return ;
2799     }
2800
2801     /* if the registers have been saved already then
2802     do nothing */
2803     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2804         return ;
2805
2806     /* find the registers in use at this time 
2807     and push them away to safety */
2808     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2809                           ic->rUsed);
2810
2811     ic->regsSaved = 1;
2812     if (options.useXstack) {
2813         if (bitVectBitValue(rsave,R0_IDX))
2814             pic16_emitcode("mov","b,r0");
2815         pic16_emitcode("mov","r0,%s",spname);
2816         for (i = 0 ; i < pic16_nRegs ; i++) {
2817             if (bitVectBitValue(rsave,i)) {
2818                 if (i == R0_IDX)
2819                     pic16_emitcode("mov","a,b");
2820                 else
2821                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2822                 pic16_emitcode("movx","@r0,a");
2823                 pic16_emitcode("inc","r0");
2824             }
2825         }
2826         pic16_emitcode("mov","%s,r0",spname);
2827         if (bitVectBitValue(rsave,R0_IDX))
2828             pic16_emitcode("mov","r0,b");           
2829     }// else
2830     //for (i = 0 ; i < pic16_nRegs ; i++) {
2831     //    if (bitVectBitValue(rsave,i))
2832     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2833     //}
2834
2835     dtype = operandType(IC_LEFT(ic));
2836     if (currFunc && dtype && 
2837         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2838         IFFUNC_ISISR(currFunc->type) &&
2839         !ic->bankSaved) 
2840
2841         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2842
2843 }
2844 /*-----------------------------------------------------------------*/
2845 /* unsaveRegisters - pop the pushed registers                      */
2846 /*-----------------------------------------------------------------*/
2847 static void unsaveRegisters (iCode *ic)
2848 {
2849     int i;
2850     bitVect *rsave;
2851
2852     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2853     /* find the registers in use at this time 
2854     and push them away to safety */
2855     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2856                           ic->rUsed);
2857     
2858     if (options.useXstack) {
2859         pic16_emitcode("mov","r0,%s",spname);   
2860         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2861             if (bitVectBitValue(rsave,i)) {
2862                 pic16_emitcode("dec","r0");
2863                 pic16_emitcode("movx","a,@r0");
2864                 if (i == R0_IDX)
2865                     pic16_emitcode("mov","b,a");
2866                 else
2867                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2868             }       
2869
2870         }
2871         pic16_emitcode("mov","%s,r0",spname);
2872         if (bitVectBitValue(rsave,R0_IDX))
2873             pic16_emitcode("mov","r0,b");
2874     } //else
2875     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2876     //    if (bitVectBitValue(rsave,i))
2877     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2878     //}
2879
2880 }  
2881 #endif
2882
2883 #if 0  // patch 14
2884 /*-----------------------------------------------------------------*/
2885 /* pushSide -                                                      */
2886 /*-----------------------------------------------------------------*/
2887 static void pushSide(operand * oper, int size)
2888 {
2889         int offset = 0;
2890     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2891         while (size--) {
2892                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2893                 if (AOP_TYPE(oper) != AOP_REG &&
2894                     AOP_TYPE(oper) != AOP_DIR &&
2895                     strcmp(l,"a") ) {
2896                         pic16_emitcode("mov","a,%s",l);
2897                         pic16_emitcode("push","acc");
2898                 } else
2899                         pic16_emitcode("push","%s",l);
2900         }
2901 }
2902 #endif // patch 14
2903
2904 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2905 {
2906   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2907     pic16_emitpcode(POC_MOVFW, src);
2908     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2909   } else {
2910     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2911         src, pic16_popGet(AOP(op), offset)));
2912   }
2913 }
2914
2915
2916 /*-----------------------------------------------------------------*/
2917 /* assignResultValue - assign results to oper, rescall==1 is       */
2918 /*                     called from genCall() or genPcall()         */
2919 /*-----------------------------------------------------------------*/
2920 static void assignResultValue(operand * oper, int rescall)
2921 {
2922   int size = AOP_SIZE(oper);
2923   int offset=0;
2924   
2925     FENTRY2;
2926 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2927     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2928
2929     if(rescall) {
2930       /* assign result from a call/pcall function() */
2931                 
2932       /* function results are stored in a special order,
2933        * see top of file with Function return policy, or manual */
2934
2935       if(size <= 4) {
2936         /* 8-bits, result in WREG */
2937         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2938                         
2939         if(size>1) {
2940           /* 16-bits, result in PRODL:WREG */
2941           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2942         }
2943                         
2944         if(size>2) {
2945           /* 24-bits, result in PRODH:PRODL:WREG */
2946           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2947         }
2948                         
2949         if(size>3) {
2950           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2951           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2952         }
2953       
2954       } else {
2955         /* >32-bits, result on stack, and FSR0 points to beginning.
2956          * Fix stack when done */
2957         /* FIXME FIXME */
2958 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2959         while (size--) {
2960 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2961 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2962                 
2963           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2964           GpsuedoStkPtr++;
2965         }
2966                         
2967         /* fix stack */
2968         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2969         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
2970         if(STACK_MODEL_LARGE) {
2971           emitSKPNC;
2972           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
2973         }
2974       }                 
2975     } else {
2976       int areg = 0;             /* matching argument register */
2977       
2978 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2979       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2980
2981
2982       /* its called from genReceive (probably) -- VR */
2983       /* I hope this code will not be called from somewhere else in the future! 
2984        * We manually set the pseudo stack pointer in genReceive. - dw
2985        */
2986       if(!GpsuedoStkPtr && _G.useWreg) {
2987 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2988
2989         /* The last byte in the assignment is in W */
2990         if(areg <= GpsuedoStkPtr) {
2991           size--;
2992           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2993           offset++;
2994 //          debugf("receive from WREG\n", 0);
2995         }
2996         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
2997       }
2998 //      GpsuedoStkPtr++;
2999       _G.stack_lat = AOP_SIZE(oper)-1;
3000
3001       while (size) {
3002         size--;
3003         GpsuedoStkPtr++;
3004         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3005 //        debugf("receive from STACK\n", 0);
3006         offset++;
3007       }
3008     }
3009 }
3010
3011
3012 /*-----------------------------------------------------------------*/
3013 /* genIpush - generate code for pushing this gets a little complex */
3014 /*-----------------------------------------------------------------*/
3015 static void genIpush (iCode *ic)
3016 {
3017 //  int size, offset=0;
3018
3019   FENTRY;
3020   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3021
3022   if(ic->parmPush) {
3023     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3024
3025     /* send to stack as normal */
3026     addSet(&_G.sendSet,ic);
3027 //    addSetHead(&_G.sendSet,ic);
3028     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3029   }
3030
3031         
3032 #if 0
3033     int size, offset = 0 ;
3034     char *l;
3035
3036
3037     /* if this is not a parm push : ie. it is spill push 
3038     and spill push is always done on the local stack */
3039     if (!ic->parmPush) {
3040
3041         /* and the item is spilt then do nothing */
3042         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3043             return ;
3044
3045         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3046         size = AOP_SIZE(IC_LEFT(ic));
3047         /* push it on the stack */
3048         while(size--) {
3049             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3050             if (*l == '#') {
3051                 MOVA(l);
3052                 l = "acc";
3053             }
3054             pic16_emitcode("push","%s",l);
3055         }
3056         return ;        
3057     }
3058
3059     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3060 #endif
3061 }
3062
3063 /*-----------------------------------------------------------------*/
3064 /* genIpop - recover the registers: can happen only for spilling   */
3065 /*-----------------------------------------------------------------*/
3066 static void genIpop (iCode *ic)
3067 {
3068   FENTRY;
3069   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3070 #if 0
3071     int size,offset ;
3072
3073
3074     /* if the temp was not pushed then */
3075     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3076         return ;
3077
3078     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3079     size = AOP_SIZE(IC_LEFT(ic));
3080     offset = (size-1);
3081     while (size--) 
3082         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3083                                    FALSE,TRUE));
3084
3085     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3086 #endif
3087 }
3088
3089 #if 0
3090 /*-----------------------------------------------------------------*/
3091 /* unsaverbank - restores the resgister bank from stack            */
3092 /*-----------------------------------------------------------------*/
3093 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3094 {
3095   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3096 #if 0
3097     int i;
3098     asmop *aop ;
3099     regs *r = NULL;
3100
3101     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3102     if (popPsw) {
3103         if (options.useXstack) {
3104             aop = newAsmop(0);
3105             r = getFreePtr(ic,&aop,FALSE);
3106             
3107             
3108             pic16_emitcode("mov","%s,_spx",r->name);
3109             pic16_emitcode("movx","a,@%s",r->name);
3110             pic16_emitcode("mov","psw,a");
3111             pic16_emitcode("dec","%s",r->name);
3112             
3113         }else
3114             pic16_emitcode ("pop","psw");
3115     }
3116
3117     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3118         if (options.useXstack) {       
3119             pic16_emitcode("movx","a,@%s",r->name);
3120             //pic16_emitcode("mov","(%s+%d),a",
3121             //       regspic16[i].base,8*bank+regspic16[i].offset);
3122             pic16_emitcode("dec","%s",r->name);
3123
3124         } else 
3125           pic16_emitcode("pop",""); //"(%s+%d)",
3126         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3127     }
3128
3129     if (options.useXstack) {
3130
3131         pic16_emitcode("mov","_spx,%s",r->name);
3132         pic16_freeAsmop(NULL,aop,ic,TRUE);
3133
3134     }
3135 #endif 
3136 }
3137
3138 /*-----------------------------------------------------------------*/
3139 /* saverbank - saves an entire register bank on the stack          */
3140 /*-----------------------------------------------------------------*/
3141 static void saverbank (int bank, iCode *ic, bool pushPsw)
3142 {
3143   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3144 #if 0
3145     int i;
3146     asmop *aop ;
3147     regs *r = NULL;
3148
3149     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3150     if (options.useXstack) {
3151
3152         aop = newAsmop(0);
3153         r = getFreePtr(ic,&aop,FALSE);  
3154         pic16_emitcode("mov","%s,_spx",r->name);
3155
3156     }
3157
3158     for (i = 0 ; i < pic16_nRegs ;i++) {
3159         if (options.useXstack) {
3160             pic16_emitcode("inc","%s",r->name);
3161             //pic16_emitcode("mov","a,(%s+%d)",
3162             //         regspic16[i].base,8*bank+regspic16[i].offset);
3163             pic16_emitcode("movx","@%s,a",r->name);           
3164         } else 
3165           pic16_emitcode("push","");// "(%s+%d)",
3166                      //regspic16[i].base,8*bank+regspic16[i].offset);
3167     }
3168     
3169     if (pushPsw) {
3170         if (options.useXstack) {
3171             pic16_emitcode("mov","a,psw");
3172             pic16_emitcode("movx","@%s,a",r->name);     
3173             pic16_emitcode("inc","%s",r->name);
3174             pic16_emitcode("mov","_spx,%s",r->name);       
3175             pic16_freeAsmop (NULL,aop,ic,TRUE);
3176             
3177         } else
3178             pic16_emitcode("push","psw");
3179         
3180         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3181     }
3182     ic->bankSaved = 1;
3183 #endif
3184 }
3185 #endif  /* 0 */
3186
3187
3188 static int wparamCmp(void *p1, void *p2)
3189 {
3190   return (!strcmp((char *)p1, (char *)p2));
3191 }
3192
3193 int inWparamList(char *s)
3194 {
3195   return isinSetWith(wparamList, s, wparamCmp);
3196
3197
3198
3199 /*-----------------------------------------------------------------*/
3200 /* genCall - generates a call statement                            */
3201 /*-----------------------------------------------------------------*/
3202 static void genCall (iCode *ic)
3203 {
3204   sym_link *ftype;   
3205   int stackParms=0;
3206   int use_wreg=0;
3207   int inwparam=0;
3208   char *fname;
3209   
3210     FENTRY;
3211
3212     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3213     /* if caller saves & we have not saved then */
3214 //    if (!ic->regsSaved)
3215 //      saveRegisters(ic);
3216
3217         /* initialise stackParms for IPUSH pushes */
3218 //      stackParms = psuedoStkPtr;
3219 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3220     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3221     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3222
3223 #if 0
3224     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3225 #endif
3226
3227     /* if send set is not empty the assign */
3228     if (_G.sendSet) {
3229       iCode *sic;
3230       int psuedoStkPtr=-1; 
3231       int firstTimeThruLoop = 1;
3232
3233
3234         /* reverse sendSet if function is not reentrant */
3235         if(!IFFUNC_ISREENT(ftype))
3236           _G.sendSet = reverseSet(_G.sendSet);
3237
3238         /* First figure how many parameters are getting passed */
3239         stackParms = 0;
3240         use_wreg = 0;
3241         
3242         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3243           int size;
3244 //          int offset = 0;
3245
3246             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3247             size = AOP_SIZE(IC_LEFT(sic));
3248
3249             stackParms += size;
3250
3251             /* pass the last byte through WREG */
3252             if(inwparam) {
3253
3254               while (size--) {
3255                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3256                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3257                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3258
3259                 if(!firstTimeThruLoop) {
3260                   /* If this is not the first time we've been through the loop
3261                    * then we need to save the parameter in a temporary
3262                    * register. The last byte of the last parameter is
3263                    * passed in W. */
3264
3265                   pushw();
3266 //                  --psuedoStkPtr;             // sanity check
3267                   use_wreg = 1;
3268                 }
3269                 
3270                 firstTimeThruLoop=0;
3271
3272                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3273
3274 //                offset++;
3275               }
3276             } else {
3277               /* all arguments are passed via stack */
3278               use_wreg = 0;
3279
3280               while (size--) {
3281                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3282                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3283                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3284
3285 //                pushaop(AOP(IC_LEFT(sic)), size);
3286                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3287
3288                 if(!_G.resDirect)
3289                   pushw();
3290               }
3291             }
3292
3293             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3294           }
3295
3296           if(inwparam) {
3297             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3298               pushw();  /* save last parameter to stack if functions has varargs */
3299               use_wreg = 0;
3300             } else
3301               use_wreg = 1;
3302           } else use_wreg = 0;
3303
3304           _G.stackRegSet = _G.sendSet;
3305           _G.sendSet = NULL;
3306     }
3307
3308     /* make the call */
3309     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3310
3311     GpsuedoStkPtr=0;
3312     
3313     /* if we need to assign a result value */
3314     if ((IS_ITEMP(IC_RESULT(ic))
3315           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3316               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3317         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3318
3319       _G.accInUse++;
3320       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3321       _G.accInUse--;
3322
3323       assignResultValue(IC_RESULT(ic), 1);
3324
3325       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3326                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3327                 
3328       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3329     }
3330
3331     if(!stackParms && ic->parmBytes) {
3332       stackParms = ic->parmBytes;
3333     }
3334       
3335     stackParms -= use_wreg;
3336     
3337     if(stackParms>0) {
3338       if(stackParms == 1) {
3339         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3340       } else {
3341         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3342         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3343       }
3344       if(STACK_MODEL_LARGE) {
3345         emitSKPNC;
3346         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3347       }
3348     }
3349
3350 #if 0
3351     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3352 #endif
3353
3354     /* adjust the stack for parameters if required */
3355 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3356
3357 #if 0
3358       /* if register bank was saved then pop them */
3359       if (ic->bankSaved)
3360         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3361
3362       /* if we hade saved some registers then unsave them */
3363       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3364         unsaveRegisters (ic);
3365 #endif
3366 }
3367
3368
3369
3370 /*-----------------------------------------------------------------*/
3371 /* genPcall - generates a call by pointer statement                */
3372 /*            new version, created from genCall - HJD              */
3373 /*-----------------------------------------------------------------*/
3374 static void genPcall (iCode *ic)
3375 {
3376   sym_link *ftype, *fntype;
3377   int stackParms=0;
3378   symbol *retlbl = newiTempLabel(NULL);
3379   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3380   
3381     FENTRY;
3382
3383     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3384     fntype = operandType( IC_LEFT(ic) )->next;
3385
3386     /* if send set is not empty the assign */
3387     if (_G.sendSet) {
3388       iCode *sic;
3389       int psuedoStkPtr=-1; 
3390
3391       /* reverse sendSet if function is not reentrant */
3392       if(!IFFUNC_ISREENT(fntype))
3393         _G.sendSet = reverseSet(_G.sendSet);
3394
3395       stackParms = 0;
3396       
3397       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3398         int size;
3399
3400           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3401           size = AOP_SIZE(IC_LEFT(sic));
3402           stackParms += size;
3403
3404           /* all parameters are passed via stack, since WREG is clobbered
3405            * by the calling sequence */
3406           while (size--) {
3407             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3408             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3409             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3410
3411             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3412             pushw();
3413           }
3414
3415           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3416       }
3417
3418       _G.stackRegSet = _G.sendSet;
3419       _G.sendSet = NULL;
3420     }
3421
3422     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3423
3424     // push return address
3425     // push $ on return stack, then replace with retlbl
3426
3427     /* Thanks to Thorsten Klose for pointing out that the following
3428      * snippet should be interrupt safe */
3429     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3430     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3431
3432     pic16_emitpcodeNULLop(POC_PUSH);
3433
3434     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3435     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3436     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3437     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3438     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3439     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3440
3441
3442     /* restore interrupt control register */
3443     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3444     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3445
3446     /* make the call by writing the pointer into pc */
3447     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3448     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3449
3450     // note: MOVFF to PCL not allowed
3451     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3452     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3453
3454
3455     /* return address is here: (X) */
3456     pic16_emitpLabelFORCE(retlbl->key);
3457
3458     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3459
3460     GpsuedoStkPtr=0;
3461     /* if we need assign a result value */
3462     if ((IS_ITEMP(IC_RESULT(ic))
3463           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3464               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3465         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3466
3467       _G.accInUse++;
3468       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3469       _G.accInUse--;
3470
3471       assignResultValue(IC_RESULT(ic), 1);
3472
3473       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3474               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3475                 
3476       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3477     }
3478
3479 //    stackParms -= use_wreg;
3480     
3481     if(stackParms>0) {
3482       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3483       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3484       if(STACK_MODEL_LARGE) {
3485         emitSKPNC;
3486         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3487       }
3488     }
3489 }
3490
3491 /*-----------------------------------------------------------------*/
3492 /* resultRemat - result  is rematerializable                       */
3493 /*-----------------------------------------------------------------*/
3494 static int resultRemat (iCode *ic)
3495 {
3496   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3497   if (SKIP_IC(ic) || ic->op == IFX)
3498     return 0;
3499
3500   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3501     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3502     if (sym->remat && !POINTER_SET(ic)) 
3503       return 1;
3504   }
3505
3506   return 0;
3507 }
3508
3509 #if defined(__BORLANDC__) || defined(_MSC_VER)
3510 #define STRCASECMP stricmp
3511 #else
3512 #define STRCASECMP strcasecmp
3513 #endif
3514
3515 #if 0
3516 /*-----------------------------------------------------------------*/
3517 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3518 /*-----------------------------------------------------------------*/
3519 static bool inExcludeList(char *s)
3520 {
3521   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3522     int i =0;
3523     
3524     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3525     if (options.excludeRegs[i] &&
3526     STRCASECMP(options.excludeRegs[i],"none") == 0)
3527         return FALSE ;
3528
3529     for ( i = 0 ; options.excludeRegs[i]; i++) {
3530         if (options.excludeRegs[i] &&
3531         STRCASECMP(s,options.excludeRegs[i]) == 0)
3532             return TRUE;
3533     }
3534     return FALSE ;
3535 }
3536 #endif
3537
3538 /*-----------------------------------------------------------------*/
3539 /* genFunction - generated code for function entry                 */
3540 /*-----------------------------------------------------------------*/
3541 static void genFunction (iCode *ic)
3542 {
3543   symbol *sym;
3544   sym_link *ftype;
3545   
3546     FENTRY;
3547     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3548
3549     pic16_labelOffset += (max_key+4);
3550     max_key=0;
3551     GpsuedoStkPtr=0;
3552     _G.nRegsSaved = 0;
3553         
3554     ftype = operandType(IC_LEFT(ic));
3555     sym = OP_SYMBOL(IC_LEFT(ic));
3556
3557     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3558       /* create an absolute section at the interrupt vector:
3559        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3560       symbol *asym;
3561       char asymname[128];
3562       pBlock *apb;
3563
3564 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3565
3566         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3567           sprintf(asymname, "ivec_%s", sym->name);
3568         else
3569           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3570   
3571         /* when an interrupt is declared as naked, do not emit the special
3572          * wrapper segment at vector address. The user should take care for
3573          * this instead. -- VR */
3574
3575         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3576           asym = newSymbol(asymname, 0);
3577           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3578           pic16_addpBlock( apb );
3579
3580           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3581           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3582           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3583           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3584           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3585                 
3586           /* mark the end of this tiny function */
3587           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3588         } else {
3589           sprintf(asymname, "%s", sym->rname);
3590         }
3591
3592         {
3593           absSym *abSym;
3594
3595             abSym = Safe_calloc(1, sizeof(absSym));
3596             strcpy(abSym->name, asymname);
3597
3598             switch( FUNC_INTNO(sym->type) ) {
3599               case 0: abSym->address = 0x000000; break;
3600               case 1: abSym->address = 0x000008; break;
3601               case 2: abSym->address = 0x000018; break;
3602               
3603               default:
3604 //                fprintf(stderr, "no interrupt number is given\n");
3605                 abSym->address = -1; break;
3606             }
3607
3608             /* relocate interrupt vectors if needed */
3609             if(abSym->address != -1)
3610               abSym->address += pic16_options.ivt_loc;
3611
3612             addSet(&absSymSet, abSym);
3613         }
3614     }
3615
3616     /* create the function header */
3617     pic16_emitcode(";","-----------------------------------------");
3618     pic16_emitcode(";"," function %s",sym->name);
3619     pic16_emitcode(";","-----------------------------------------");
3620
3621     pic16_emitcode("","%s:",sym->rname);
3622     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3623
3624     {
3625       absSym *ab;
3626
3627         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3628           if(!strcmp(ab->name, sym->rname)) {
3629             pic16_pBlockConvert2Absolute(pb);
3630             break;
3631           }
3632         }
3633     }
3634
3635     if(IFFUNC_ISNAKED(ftype)) {
3636       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3637       return;
3638     }
3639         
3640     /* if critical function then turn interrupts off */
3641     if (IFFUNC_ISCRITICAL(ftype)) {
3642       //pic16_emitcode("clr","ea");
3643     }
3644
3645     currFunc = sym;             /* update the currFunc symbol */
3646     _G.fregsUsed = sym->regsUsed;
3647     _G.sregsAlloc = newBitVect(128);
3648     
3649
3650     /* if this is an interrupt service routine then
3651      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3652     if (IFFUNC_ISISR(sym->type)) {
3653         _G.usefastretfie = 1;   /* use shadow registers by default */
3654         
3655         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3656         if(!FUNC_ISSHADOWREGS(sym->type)) {
3657           /* do not save WREG,STATUS,BSR for high priority interrupts
3658            * because they are stored in the hardware shadow registers already */
3659           _G.usefastretfie = 0;
3660           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3661           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3662           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3663         }
3664
3665         /* these should really be optimized somehow, because not all
3666          * interrupt handlers modify them */
3667         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3668         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3669         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3670         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3671         
3672 //        pic16_pBlockConvert2ISR(pb);
3673     }
3674
3675     /* emit code to setup stack frame if user enabled,
3676      * and function is not main() */
3677     
3678 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3679     if(strcmp(sym->name, "main")) {
3680       if(0 
3681         || !options.ommitFramePtr 
3682 //        || sym->regsUsed
3683         || IFFUNC_ARGS(sym->type)
3684         || FUNC_HASSTACKPARM(sym->etype)
3685         ) {
3686         /* setup the stack frame */
3687         if(STACK_MODEL_LARGE)
3688           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3689         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3690
3691         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3692         if(STACK_MODEL_LARGE)
3693           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3694       }
3695     }
3696
3697     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3698           && sym->stack) {
3699
3700       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3701
3702       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3703       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3704       emitSKPC;
3705       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3706     }
3707           
3708     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3709       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3710         _G.useWreg = 0;
3711       else
3712         _G.useWreg = 1;
3713     } else
3714       _G.useWreg = 0;
3715
3716     /* if callee-save to be used for this function
3717      * then save the registers being used in this function */
3718 //    if (IFFUNC_CALLEESAVES(sym->type))
3719     {
3720       int i;
3721
3722         /* if any registers used */
3723         if (sym->regsUsed) {
3724           /* save the registers used */
3725           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3726           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3727           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3728             if (bitVectBitValue(sym->regsUsed,i)) {
3729               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3730               _G.nRegsSaved++;
3731
3732               if(!pic16_regWithIdx(i)->wasUsed) {
3733                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3734                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3735                 pic16_regWithIdx(i)->wasUsed = 1;
3736               }
3737             }
3738           }
3739           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3740         }
3741     }
3742         
3743     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3744 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3745 }
3746
3747 /*-----------------------------------------------------------------*/
3748 /* genEndFunction - generates epilogue for functions               */
3749 /*-----------------------------------------------------------------*/
3750 static void genEndFunction (iCode *ic)
3751 {
3752   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3753
3754     FENTRY;
3755
3756     if(IFFUNC_ISNAKED(sym->type)) {
3757       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3758       return;
3759     }
3760
3761     _G.stack_lat = 0;
3762
3763     /* add code for ISCRITICAL */
3764     if(IFFUNC_ISCRITICAL(sym->type)) {
3765       /* if critical function, turn on interrupts */
3766       
3767       /* TODO: add code here -- VR */
3768     }
3769     
3770 //    sym->regsUsed = _G.fregsUsed;
3771     
3772     /* now we need to restore the registers */
3773     /* if any registers used */
3774
3775     /* first restore registers that might be used for stack access */
3776     if(_G.sregsAllocSet) {
3777     regs *sr;
3778     
3779       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3780       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3781         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3782       }
3783     }
3784
3785     if (sym->regsUsed) {
3786       int i;
3787
3788         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3789         /* restore registers used */
3790         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3791         for ( i = sym->regsUsed->size; i >= 0; i--) {
3792           if (bitVectBitValue(sym->regsUsed,i)) {
3793             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3794             _G.nRegsSaved--;
3795           }
3796         }
3797         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3798     }
3799
3800       
3801
3802     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3803           && sym->stack) {
3804       if (sym->stack == 1) {
3805         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3806         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3807       } else {
3808         // we have to add more than one...
3809         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3810         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3811         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3812         emitSKPNC;
3813         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3814         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3815         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3816       }
3817     }
3818
3819     if(strcmp(sym->name, "main")) {
3820       if(0
3821         || !options.ommitFramePtr
3822 //        || sym->regsUsed
3823         || IFFUNC_ARGS(sym->type)
3824         || FUNC_HASSTACKPARM(sym->etype)
3825         ) {
3826         /* restore stack frame */
3827         if(STACK_MODEL_LARGE)
3828           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3829         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3830       }
3831     }
3832
3833     _G.useWreg = 0;
3834
3835     if (IFFUNC_ISISR(sym->type)) {
3836       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3837       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3838       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3839       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3840
3841       if(!FUNC_ISSHADOWREGS(sym->type)) {
3842         /* do not restore interrupt vector for WREG,STATUS,BSR
3843          * for high priority interrupt, see genFunction */
3844         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3845         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3846         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3847       }
3848 //      _G.interruptvector = 0;         /* sanity check */
3849
3850
3851       /* if debug then send end of function */
3852 /*      if (options.debug && currFunc)  */
3853       if (currFunc) {
3854         debugFile->writeEndFunction (currFunc, ic, 1);
3855       }
3856         
3857       if(_G.usefastretfie)
3858         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3859       else
3860         pic16_emitpcodeNULLop(POC_RETFIE);
3861
3862       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3863       
3864       _G.usefastretfie = 0;
3865       return;
3866     }
3867
3868     if (IFFUNC_ISCRITICAL(sym->type)) {
3869       pic16_emitcode("setb","ea");
3870     }
3871
3872     /* if debug then send end of function */
3873     if (currFunc) {
3874       debugFile->writeEndFunction (currFunc, ic, 1);
3875     }
3876
3877     /* insert code to restore stack frame, if user enabled it
3878      * and function is not main() */
3879          
3880
3881     pic16_emitpcodeNULLop(POC_RETURN);
3882
3883     /* Mark the end of a function */
3884     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3885 }
3886
3887
3888 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3889 {
3890   unsigned long lit=1;
3891   operand *op;
3892
3893     op = IC_LEFT(ic);
3894   
3895     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3896     if(AOP_TYPE(op) == AOP_LIT) {
3897       if(!IS_FLOAT(operandType( op ))) {
3898         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3899       } else {
3900         union {
3901           unsigned long lit_int;
3902           float lit_float;
3903         } info;
3904         
3905         /* take care if literal is a float */
3906         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3907         lit = info.lit_int;
3908       }
3909     }
3910
3911     if(is_LitOp(op)) {
3912       if(/*(OP_LIVETO(op) <= ic->seq) &&*/ (lit == 0)) {
3913         pic16_emitpcode(POC_CLRF, dest);
3914       } else {
3915         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3916         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3917       }
3918     } else {
3919       if(dest->type == PO_WREG && (offset == 0)) {
3920         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3921       return;
3922     }
3923     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3924   }
3925 }
3926
3927 /*-----------------------------------------------------------------*/
3928 /* genRet - generate code for return statement                     */
3929 /*-----------------------------------------------------------------*/
3930 static void genRet (iCode *ic)
3931 {
3932   int size;
3933   operand *left;
3934
3935     FENTRY;
3936         /* if we have no return value then
3937          * just generate the "ret" */
3938         
3939         if (!IC_LEFT(ic)) 
3940                 goto jumpret;       
3941     
3942         /* we have something to return then
3943          * move the return value into place */
3944         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3945         size = AOP_SIZE(IC_LEFT(ic));
3946
3947         if(size <= 4) {
3948           if(size>3)
3949             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3950           
3951           if(size>2)
3952             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
3953
3954           if(size>1)
3955             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
3956           
3957           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
3958
3959         } else {
3960                 /* >32-bits, setup stack and FSR0 */
3961                 while (size--) {
3962 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3963 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3964
3965                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3966
3967 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3968                         GpsuedoStkPtr++;
3969                 }
3970                         
3971                 /* setup FSR0 */
3972                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3973                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3974
3975                 if(STACK_MODEL_LARGE) {
3976                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3977                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3978                 } else {
3979                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3980                 }
3981         }
3982                                 
3983 #if 0
3984         /* old code, left here for reference -- VR */    
3985         while (size--) {
3986           char *l ;
3987
3988                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3989                         /* #NOCHANGE */
3990                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3991                         pic16_emitpcomment("push %s",l);
3992                         pushed++;
3993                 } else {
3994                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3995                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3996                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3997                         
3998                         if (strcmp(fReturn[offset],l)) {
3999                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4000                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4001                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4002                                 } else {
4003                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4004                                 }
4005                                 
4006                                 if(size) {
4007                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4008                                 }
4009                                 offset++;
4010                         }
4011                 }
4012         }    
4013
4014         if (pushed) {
4015                 while(pushed) {
4016                         pushed--;
4017                         if (strcmp(fReturn[pushed],"a"))
4018                                 pic16_emitcode("pop",fReturn[pushed]);
4019                         else
4020                                 pic16_emitcode("pop","acc");
4021                 }
4022         }
4023 #endif
4024
4025
4026         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4027     
4028 jumpret:
4029         /* generate a jump to the return label
4030          * if the next is not the return statement */
4031         if (!(ic->next && ic->next->op == LABEL
4032                 && IC_LABEL(ic->next) == returnLabel)) {
4033         
4034                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4035                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4036         }
4037 }
4038
4039 /*-----------------------------------------------------------------*/
4040 /* genLabel - generates a label                                    */
4041 /*-----------------------------------------------------------------*/
4042 static void genLabel (iCode *ic)
4043 {
4044   FENTRY;
4045
4046   /* special case never generate */
4047   if (IC_LABEL(ic) == entryLabel)
4048     return ;
4049
4050   pic16_emitpLabel(IC_LABEL(ic)->key);
4051 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4052 }
4053
4054 /*-----------------------------------------------------------------*/
4055 /* genGoto - generates a goto                                      */
4056 /*-----------------------------------------------------------------*/
4057 //tsd
4058 static void genGoto (iCode *ic)
4059 {
4060   FENTRY;
4061   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4062 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4063 }
4064
4065
4066 /*-----------------------------------------------------------------*/
4067 /* genMultbits :- multiplication of bits                           */
4068 /*-----------------------------------------------------------------*/
4069 static void genMultbits (operand *left, 
4070                          operand *right, 
4071                          operand *result)
4072 {
4073   FENTRY;
4074
4075   if(!pic16_sameRegs(AOP(result),AOP(right)))
4076     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4077
4078   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4079   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4080   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4081
4082 }
4083
4084
4085 /*-----------------------------------------------------------------*/
4086 /* genMultOneByte : 8 bit multiplication & division                */
4087 /*-----------------------------------------------------------------*/
4088 static void genMultOneByte (operand *left,
4089                             operand *right,
4090                             operand *result)
4091 {
4092
4093   FENTRY;
4094   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4095   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4096
4097   /* (if two literals, the value is computed before) */
4098   /* if one literal, literal on the right */
4099   if (AOP_TYPE(left) == AOP_LIT){
4100     operand *t = right;
4101     right = left;
4102     left = t;
4103   }
4104
4105         /* size is already checked in genMult == 1 */
4106 //      size = AOP_SIZE(result);
4107
4108         if (AOP_TYPE(right) == AOP_LIT){
4109                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4110                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4111                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4112                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4113         } else {
4114                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4115                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4116                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4117                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4118         }
4119         
4120         pic16_genMult8X8_8 (left, right,result);
4121 }
4122
4123 /*-----------------------------------------------------------------*/
4124 /* genMultOneWord : 16 bit multiplication                          */
4125 /*-----------------------------------------------------------------*/
4126 static void genMultOneWord (operand *left,
4127                             operand *right,
4128                             operand *result)
4129 {
4130   FENTRY;
4131   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4132   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4133
4134   /* (if two literals, the value is computed before)
4135    * if one literal, literal on the right */
4136   if (AOP_TYPE(left) == AOP_LIT){
4137     operand *t = right;
4138     right = left;
4139     left = t;
4140   }
4141
4142   /* size is checked already == 2 */
4143 //  size = AOP_SIZE(result);
4144
4145   if (AOP_TYPE(right) == AOP_LIT) {
4146     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4147       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4148       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4149       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4150   } else {
4151     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4152       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4153       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4154       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4155   }
4156         
4157   pic16_genMult16X16_16(left, right,result);
4158 }
4159
4160 /*-----------------------------------------------------------------*/
4161 /* genMultOneLong : 32 bit multiplication                          */
4162 /*-----------------------------------------------------------------*/
4163 static void genMultOneLong (operand *left,
4164                             operand *right,
4165                             operand *result)
4166 {
4167   FENTRY;
4168   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4169   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4170
4171   /* (if two literals, the value is computed before)
4172    * if one literal, literal on the right */
4173   if (AOP_TYPE(left) == AOP_LIT){
4174     operand *t = right;
4175     right = left;
4176     left = t;
4177   }
4178
4179   /* size is checked already == 4 */
4180 //  size = AOP_SIZE(result);
4181
4182   if (AOP_TYPE(right) == AOP_LIT) {
4183     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4184         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4185         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4186         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4187   } else {
4188     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4189         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4190         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4191         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4192   }
4193         
4194   pic16_genMult32X32_32(left, right,result);
4195 }
4196
4197
4198
4199 /*-----------------------------------------------------------------*/
4200 /* genMult - generates code for multiplication                     */
4201 /*-----------------------------------------------------------------*/
4202 static void genMult (iCode *ic)
4203 {
4204   operand *left = IC_LEFT(ic);
4205   operand *right = IC_RIGHT(ic);
4206   operand *result= IC_RESULT(ic);   
4207
4208     FENTRY;
4209         /* assign the amsops */
4210         pic16_aopOp (left,ic,FALSE);
4211         pic16_aopOp (right,ic,FALSE);
4212         pic16_aopOp (result,ic,TRUE);
4213
4214         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4215
4216         /* special cases first *
4217         * both are bits */
4218         if (AOP_TYPE(left) == AOP_CRY
4219                 && AOP_TYPE(right)== AOP_CRY) {
4220                 genMultbits(left,right,result);
4221           goto release ;
4222         }
4223
4224         /* if both are of size == 1 */
4225         if(AOP_SIZE(left) == 1
4226                 && AOP_SIZE(right) == 1) {
4227                 genMultOneByte(left,right,result);
4228           goto release ;
4229         }
4230
4231         /* if both are of size == 2 */
4232         if(AOP_SIZE(left) == 2
4233                 && AOP_SIZE(right) == 2) {
4234                 genMultOneWord(left, right, result);
4235           goto release;
4236         }
4237         
4238         /* if both are of size == 4 */
4239         if(AOP_SIZE(left) == 4
4240                 && AOP_SIZE(right) == 4) {
4241                 genMultOneLong(left, right, result);
4242           goto release;
4243         }
4244         
4245         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4246
4247
4248         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4249         /* should have been converted to function call */
4250         assert(0) ;
4251
4252 release :
4253         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4254         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4255         pic16_freeAsmop(result,NULL,ic,TRUE); 
4256 }
4257
4258 /*-----------------------------------------------------------------*/
4259 /* genDivbits :- division of bits                                  */
4260 /*-----------------------------------------------------------------*/
4261 static void genDivbits (operand *left, 
4262                         operand *right, 
4263                         operand *result)
4264 {
4265   char *l;
4266
4267     FENTRY;
4268     /* the result must be bit */    
4269     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4270     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4271
4272     MOVA(l);    
4273
4274     pic16_emitcode("div","ab");
4275     pic16_emitcode("rrc","a");
4276     pic16_aopPut(AOP(result),"c",0);
4277 }
4278
4279 /*-----------------------------------------------------------------*/
4280 /* genDivOneByte : 8 bit division                                  */
4281 /*-----------------------------------------------------------------*/
4282 static void genDivOneByte (operand *left,
4283                            operand *right,
4284                            operand *result)
4285 {
4286   sym_link *opetype = operandType(result);
4287   char *l ;
4288   symbol *lbl ;
4289   int size,offset;
4290
4291         /* result = divident / divisor
4292          * - divident may be a register or a literal,
4293          * - divisor may be a register or a literal,
4294          * so there are 3 cases (literal / literal is optimized
4295          * by the front-end) to handle.
4296          * In addition we must handle signed and unsigned, which
4297          * result in 6 final different cases -- VR */
4298
4299     FENTRY;
4300     
4301     size = AOP_SIZE(result) - 1;
4302     offset = 1;
4303     /* signed or unsigned */
4304     if (SPEC_USIGN(opetype)) {
4305       pCodeOp *pct1,    /* count */
4306                 *pct2,  /* reste */
4307                 *pct3;  /* temp */
4308       symbol *label1, *label2, *label3;;
4309
4310
4311         /* unsigned is easy */
4312
4313         pct1 = pic16_popGetTempReg(1);
4314         pct2 = pic16_popGetTempReg(1);
4315         pct3 = pic16_popGetTempReg(1);
4316         
4317         label1 = newiTempLabel(NULL);
4318         label2 = newiTempLabel(NULL);
4319         label3 = newiTempLabel(NULL);
4320
4321         /* the following algorithm is extracted from divuint.c */
4322
4323         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4324         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4325         
4326         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4327
4328         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4329         
4330         pic16_emitpLabel(label1->key);
4331         
4332         emitCLRC;
4333         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4334
4335
4336         emitCLRC;
4337         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4338         
4339
4340         emitSKPNC;
4341         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4342         
4343         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4344         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4345         
4346         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4347         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4348         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4349         
4350         pic16_emitpLabel( label3->key );
4351         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4352         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4353         
4354         
4355
4356         pic16_emitpLabel(label2->key);
4357         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4358         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4359         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4360         
4361         /* result is in wreg */
4362         if(AOP_TYPE(result) != AOP_ACC)
4363                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4364
4365         pic16_popReleaseTempReg( pct3, 1);
4366         pic16_popReleaseTempReg( pct2, 1);
4367         pic16_popReleaseTempReg( pct1, 1);
4368
4369         return ;
4370     }
4371
4372     /* signed is a little bit more difficult */
4373
4374     /* save the signs of the operands */
4375     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4376     MOVA(l);    
4377     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4378     pic16_emitcode("push","acc"); /* save it on the stack */
4379
4380     /* now sign adjust for both left & right */
4381     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4382     MOVA(l);       
4383     lbl = newiTempLabel(NULL);
4384     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4385     pic16_emitcode("cpl","a");   
4386     pic16_emitcode("inc","a");
4387     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4388     pic16_emitcode("mov","b,a");
4389
4390     /* sign adjust left side */
4391     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4392     MOVA(l);
4393
4394     lbl = newiTempLabel(NULL);
4395     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4396     pic16_emitcode("cpl","a");
4397     pic16_emitcode("inc","a");
4398     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4399
4400     /* now the division */
4401     pic16_emitcode("div","ab");
4402     /* we are interested in the lower order
4403     only */
4404     pic16_emitcode("mov","b,a");
4405     lbl = newiTempLabel(NULL);
4406     pic16_emitcode("pop","acc");   
4407     /* if there was an over flow we don't 
4408     adjust the sign of the result */
4409     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4410     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4411     CLRC;
4412     pic16_emitcode("clr","a");
4413     pic16_emitcode("subb","a,b");
4414     pic16_emitcode("mov","b,a");
4415     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4416
4417     /* now we are done */
4418     pic16_aopPut(AOP(result),"b",0);
4419     if(size > 0){
4420         pic16_emitcode("mov","c,b.7");
4421         pic16_emitcode("subb","a,acc");   
4422     }
4423     while (size--)
4424         pic16_aopPut(AOP(result),"a",offset++);
4425
4426 }
4427
4428 /*-----------------------------------------------------------------*/
4429 /* genDiv - generates code for division                            */
4430 /*-----------------------------------------------------------------*/
4431 static void genDiv (iCode *ic)
4432 {
4433     operand *left = IC_LEFT(ic);
4434     operand *right = IC_RIGHT(ic);
4435     operand *result= IC_RESULT(ic);   
4436
4437
4438         /* Division is a very lengthy algorithm, so it is better
4439          * to call support routines than inlining algorithm.
4440          * Division functions written here just in case someone
4441          * wants to inline and not use the support libraries -- VR */
4442
4443     FENTRY;
4444     
4445     /* assign the amsops */
4446     pic16_aopOp (left,ic,FALSE);
4447     pic16_aopOp (right,ic,FALSE);
4448     pic16_aopOp (result,ic,TRUE);
4449
4450     /* special cases first */
4451     /* both are bits */
4452     if (AOP_TYPE(left) == AOP_CRY &&
4453         AOP_TYPE(right)== AOP_CRY) {
4454         genDivbits(left,right,result);
4455         goto release ;
4456     }
4457
4458     /* if both are of size == 1 */
4459     if (AOP_SIZE(left) == 1 &&
4460         AOP_SIZE(right) == 1 ) {
4461         genDivOneByte(left,right,result);
4462         goto release ;
4463     }
4464
4465     /* should have been converted to function call */
4466     assert(0);
4467 release :
4468     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4469     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4470     pic16_freeAsmop(result,NULL,ic,TRUE); 
4471 }
4472
4473 /*-----------------------------------------------------------------*/
4474 /* genModbits :- modulus of bits                                   */
4475 /*-----------------------------------------------------------------*/
4476 static void genModbits (operand *left, 
4477                         operand *right, 
4478                         operand *result)
4479 {
4480   char *l;
4481
4482     FENTRY;  
4483     
4484     werror(W_POSSBUG2, __FILE__, __LINE__);
4485     /* the result must be bit */    
4486     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4487     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4488
4489     MOVA(l);       
4490
4491     pic16_emitcode("div","ab");
4492     pic16_emitcode("mov","a,b");
4493     pic16_emitcode("rrc","a");
4494     pic16_aopPut(AOP(result),"c",0);
4495 }
4496
4497 /*-----------------------------------------------------------------*/
4498 /* genModOneByte : 8 bit modulus                                   */
4499 /*-----------------------------------------------------------------*/
4500 static void genModOneByte (operand *left,
4501                            operand *right,
4502                            operand *result)
4503 {
4504   sym_link *opetype = operandType(result);
4505   char *l ;
4506   symbol *lbl ;
4507
4508     FENTRY;
4509     werror(W_POSSBUG2, __FILE__, __LINE__);
4510
4511     /* signed or unsigned */
4512     if (SPEC_USIGN(opetype)) {
4513         /* unsigned is easy */
4514         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4515         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4516         MOVA(l);    
4517         pic16_emitcode("div","ab");
4518         pic16_aopPut(AOP(result),"b",0);
4519         return ;
4520     }
4521
4522     /* signed is a little bit more difficult */
4523
4524     /* save the signs of the operands */
4525     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4526     MOVA(l);
4527
4528     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4529     pic16_emitcode("push","acc"); /* save it on the stack */
4530
4531     /* now sign adjust for both left & right */
4532     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4533     MOVA(l);
4534
4535     lbl = newiTempLabel(NULL);
4536     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4537     pic16_emitcode("cpl","a");   
4538     pic16_emitcode("inc","a");
4539     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4540     pic16_emitcode("mov","b,a"); 
4541
4542     /* sign adjust left side */
4543     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4544     MOVA(l);
4545
4546     lbl = newiTempLabel(NULL);
4547     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4548     pic16_emitcode("cpl","a");   
4549     pic16_emitcode("inc","a");
4550     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4551
4552     /* now the multiplication */
4553     pic16_emitcode("div","ab");
4554     /* we are interested in the lower order
4555     only */
4556     lbl = newiTempLabel(NULL);
4557     pic16_emitcode("pop","acc");   
4558     /* if there was an over flow we don't 
4559     adjust the sign of the result */
4560     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4561     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4562     CLRC ;
4563     pic16_emitcode("clr","a");
4564     pic16_emitcode("subb","a,b");
4565     pic16_emitcode("mov","b,a");
4566     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4567
4568     /* now we are done */
4569     pic16_aopPut(AOP(result),"b",0);
4570
4571 }
4572
4573 /*-----------------------------------------------------------------*/
4574 /* genMod - generates code for division                            */
4575 /*-----------------------------------------------------------------*/
4576 static void genMod (iCode *ic)
4577 {
4578   operand *left = IC_LEFT(ic);
4579   operand *right = IC_RIGHT(ic);
4580   operand *result= IC_RESULT(ic);  
4581
4582     FENTRY;
4583     
4584     /* assign the amsops */
4585     pic16_aopOp (left,ic,FALSE);
4586     pic16_aopOp (right,ic,FALSE);
4587     pic16_aopOp (result,ic,TRUE);
4588
4589     /* special cases first */
4590     /* both are bits */
4591     if (AOP_TYPE(left) == AOP_CRY &&
4592         AOP_TYPE(right)== AOP_CRY) {
4593         genModbits(left,right,result);
4594         goto release ;
4595     }
4596
4597     /* if both are of size == 1 */
4598     if (AOP_SIZE(left) == 1 &&
4599         AOP_SIZE(right) == 1 ) {
4600         genModOneByte(left,right,result);
4601         goto release ;
4602     }
4603
4604     /* should have been converted to function call */
4605     assert(0);
4606
4607 release :
4608     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4609     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4610     pic16_freeAsmop(result,NULL,ic,TRUE); 
4611 }
4612
4613 /*-----------------------------------------------------------------*/
4614 /* genIfxJump :- will create a jump depending on the ifx           */
4615 /*-----------------------------------------------------------------*/
4616 /*
4617   note: May need to add parameter to indicate when a variable is in bit space.
4618 */
4619 static void genIfxJump (iCode *ic, char *jval)
4620 {
4621   FENTRY;
4622   
4623     /* if true label then we jump if condition
4624     supplied is true */
4625     if ( IC_TRUE(ic) ) {
4626
4627         if(strcmp(jval,"a") == 0)
4628           emitSKPZ;
4629         else if (strcmp(jval,"c") == 0)
4630           emitSKPNC;
4631         else {
4632           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4633           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4634         }
4635
4636         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4637         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4638
4639     }
4640     else {
4641         /* false label is present */
4642         if(strcmp(jval,"a") == 0)
4643           emitSKPNZ;
4644         else if (strcmp(jval,"c") == 0)
4645           emitSKPC;
4646         else {
4647           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4648           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4649         }
4650
4651         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4652         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4653
4654     }
4655
4656
4657     /* mark the icode as generated */
4658     ic->generated = 1;
4659 }
4660
4661 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4662 {
4663   FENTRY;
4664   
4665     /* if true label then we jump if condition
4666     supplied is true */
4667     if ( IC_TRUE(ic) ) {
4668       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4669       pic16_emitpcode(POC_BTFSC, jop);
4670
4671       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4672       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4673
4674     } else {
4675       /* false label is present */
4676       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4677       pic16_emitpcode(POC_BTFSS, jop);
4678           
4679       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4680       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4681     }
4682
4683
4684     /* mark the icode as generated */
4685     ic->generated = 1;
4686 }
4687
4688 #if 0
4689 // not needed ATM
4690
4691 /*-----------------------------------------------------------------*/
4692 /* genSkip                                                         */
4693 /*-----------------------------------------------------------------*/
4694 static void genSkip(iCode *ifx,int status_bit)
4695 {
4696   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4697   if(!ifx)
4698     return;
4699
4700   if ( IC_TRUE(ifx) ) {
4701     switch(status_bit) {
4702     case 'z':
4703       emitSKPNZ;
4704       break;
4705
4706     case 'c':
4707       emitSKPNC;
4708       break;
4709
4710     case 'd':
4711       emitSKPDC;
4712       break;
4713
4714     }
4715
4716     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4717     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4718
4719   } else {
4720
4721     switch(status_bit) {
4722
4723     case 'z':
4724       emitSKPZ;
4725       break;
4726
4727     case 'c':
4728       emitSKPC;
4729       break;
4730
4731     case 'd':
4732       emitSKPDC;
4733       break;
4734     }
4735     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4736     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4737
4738   }
4739
4740 }
4741 #endif
4742
4743 /*-----------------------------------------------------------------*/
4744 /* genSkipc                                                        */
4745 /*-----------------------------------------------------------------*/
4746 static void genSkipc(resolvedIfx *rifx)
4747 {
4748   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4749   
4750   if(!rifx)
4751     return;
4752
4753   if(rifx->condition)
4754     emitSKPNC;
4755   else
4756     emitSKPC;
4757
4758   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4759   rifx->generated = 1;
4760 }
4761
4762 #if !(USE_SIMPLE_GENCMP)
4763 /*-----------------------------------------------------------------*/
4764 /* genSkipz2                                                       */
4765 /*-----------------------------------------------------------------*/
4766 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4767 {
4768   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4769   
4770   if(!rifx)
4771     return;
4772
4773   if( (rifx->condition ^ invert_condition) & 1)
4774     emitSKPZ;
4775   else
4776     emitSKPNZ;
4777
4778   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4779   rifx->generated = 1;
4780 }
4781 #endif
4782
4783 #if 0
4784 /*-----------------------------------------------------------------*/
4785 /* genSkipz                                                        */
4786 /*-----------------------------------------------------------------*/
4787 static void genSkipz(iCode *ifx, int condition)
4788 {
4789   if(!ifx)
4790     return;
4791
4792   if(condition)
4793     emitSKPNZ;
4794   else
4795     emitSKPZ;
4796
4797   if ( IC_TRUE(ifx) )
4798     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4799   else
4800     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4801
4802   if ( IC_TRUE(ifx) )
4803     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4804   else
4805     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4806
4807 }
4808 #endif
4809
4810 #if !(USE_SIMPLE_GENCMP)
4811 /*-----------------------------------------------------------------*/
4812 /* genSkipCond                                                     */
4813 /*-----------------------------------------------------------------*/
4814 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4815 {
4816   if(!rifx)
4817     return;
4818
4819   if(rifx->condition)
4820     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4821   else
4822     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4823
4824
4825   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4826   rifx->generated = 1;
4827 }
4828 #endif
4829
4830 #if 0
4831 /*-----------------------------------------------------------------*/
4832 /* genChkZeroes :- greater or less than comparison                 */
4833 /*     For each byte in a literal that is zero, inclusive or the   */
4834 /*     the corresponding byte in the operand with W                */
4835 /*     returns true if any of the bytes are zero                   */
4836 /*-----------------------------------------------------------------*/
4837 static int genChkZeroes(operand *op, int lit,  int size)
4838 {
4839
4840   int i;
4841   int flag =1;
4842
4843   while(size--) {
4844     i = (lit >> (size*8)) & 0xff;
4845
4846     if(i==0) {
4847       if(flag) 
4848         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4849       else
4850         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4851       flag = 0;
4852     }
4853   }
4854
4855   return (flag==0);
4856 }
4857 #endif
4858
4859
4860 /*-----------------------------------------------------------------*/
4861 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4862 /*                  aop (if it's NOT a literal) or from lit (if    */
4863 /*                  aop is a literal)                              */
4864 /*-----------------------------------------------------------------*/
4865 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4866   if (aop->type == AOP_LIT) {
4867     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4868   } else {
4869     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4870   }
4871 }
4872
4873 /*-----------------------------------------------------------------*/
4874 /* genCmp :- greater or less than comparison                       */
4875 /*-----------------------------------------------------------------*/
4876
4877 #if USE_SIMPLE_GENCMP           /* { */
4878
4879 /* genCmp performs a left < right comparison, stores
4880  * the outcome in result (if != NULL) and generates
4881  * control flow code for the ifx (if != NULL).
4882  *
4883  * This version leaves in sequences like
4884  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4885  * which should be optmized by the peephole
4886  * optimizer - RN 2005-01-01 */
4887 static void genCmp (operand *left,operand *right,
4888                     operand *result, iCode *ifx, int sign)
4889 {
4890   resolvedIfx rIfx;
4891   int size;
4892   int offs;
4893   symbol *templbl;
4894   operand *dummy;
4895   unsigned long lit;
4896   unsigned long mask;
4897   int performedLt;
4898
4899   FENTRY;
4900   
4901   assert (left && right);
4902   assert (AOP_SIZE(left) == AOP_SIZE(right));
4903
4904   size = AOP_SIZE(right) - 1;
4905   mask = (0x100UL << (size*8)) - 1;
4906   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4907   performedLt = 1;
4908   templbl = NULL;
4909   lit = 0;
4910   
4911   resolveIfx (&rIfx, ifx);
4912
4913   /* handle for special cases */
4914   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4915       return;
4916
4917   /**********************************************************************
4918    * handle bits - bit compares are promoted to int compares seemingly! *
4919    **********************************************************************/
4920 #if 0
4921   // THIS IS COMPLETELY UNTESTED!
4922   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4923     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4924     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4925     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4926
4927     emitSETC;
4928     // 1 < {0,1} is false --> clear C by skipping the next instruction
4929     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4930     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4931     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4932     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4933     emitCLRC; // only skipped for left=0 && right=1
4934
4935     goto correct_result_in_carry;
4936   } // if
4937 #endif
4938
4939   /*************************************************
4940    * make sure that left is register (or the like) *
4941    *************************************************/
4942   if (!isAOP_REGlike(left)) {
4943     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4944     assert (isAOP_LIT(left));
4945     assert (isAOP_REGlike(right));
4946     // swap left and right
4947     // left < right <==> right > left <==> (right >= left + 1)
4948     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4949
4950     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4951       // MAXVALUE < right? always false
4952       if (performedLt) emitCLRC; else emitSETC;
4953       goto correct_result_in_carry;
4954     } // if
4955
4956     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4957     // that's why we handled it above.
4958     lit++;
4959
4960     dummy = left;
4961     left = right;
4962     right = dummy;
4963
4964     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4965   } else if (isAOP_LIT(right)) {
4966     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4967   } // if
4968
4969   assert (isAOP_REGlike(left)); // left must be register or the like
4970   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4971
4972   /*************************************************
4973    * special cases go here                         *
4974    *************************************************/
4975
4976   if (isAOP_LIT(right)) {
4977     if (!sign) {
4978       // unsigned comparison to a literal
4979       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4980       if (lit == 0) {
4981         // unsigned left < 0? always false
4982         if (performedLt) emitCLRC; else emitSETC;
4983         goto correct_result_in_carry;
4984       }
4985     } else {
4986       // signed comparison to a literal
4987       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4988       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4989         // signed left < 0x80000000? always false
4990         if (performedLt) emitCLRC; else emitSETC;
4991         goto correct_result_in_carry;
4992       } else if (lit == 0) {
4993         // compare left < 0; set CARRY if SIGNBIT(left) is set
4994         if (performedLt) emitSETC; else emitCLRC;
4995         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4996         if (performedLt) emitCLRC; else emitSETC;
4997         goto correct_result_in_carry;
4998       }
4999     } // if (!sign)
5000   } // right is literal
5001
5002   /*************************************************
5003    * perform a general case comparison             *
5004    * make sure we get CARRY==1 <==> left >= right  *
5005    *************************************************/
5006   // compare most significant bytes
5007   //DEBUGpc ("comparing bytes at offset %d", size);
5008   if (!sign) {
5009     // unsigned comparison
5010     mov2w_regOrLit (AOP(right), lit, size);
5011     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5012   } else {
5013     // signed comparison
5014     // (add 2^n to both operands then perform an unsigned comparison)
5015     if (isAOP_LIT(right)) {
5016       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5017       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5018
5019       if (litbyte == 0x80) {
5020         // left >= 0x80 -- always true, but more bytes to come
5021         pic16_mov2w (AOP(left), size);
5022         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5023         emitSETC;
5024       } else {
5025         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5026         pic16_mov2w (AOP(left), size);
5027         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5028         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5029       } // if
5030     } else {
5031       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5032       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5033       pic16_mov2w (AOP(left), size);
5034       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5035       pic16_emitpcode (POC_MOVWF, pctemp);
5036       pic16_mov2w (AOP(right), size);
5037       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5038       pic16_emitpcode (POC_SUBFW, pctemp);
5039       //pic16_popReleaseTempReg(pctemp, 1);
5040     }
5041   } // if (!sign)
5042
5043   // compare remaining bytes (treat as unsigned case from above)
5044   templbl = newiTempLabel ( NULL );
5045   offs = size;
5046   while (offs--) {
5047     //DEBUGpc ("comparing bytes at offset %d", offs);
5048     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5049     mov2w_regOrLit (AOP(right), lit, offs);
5050     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5051   } // while (offs)
5052   pic16_emitpLabel (templbl->key);
5053   goto result_in_carry;
5054
5055 result_in_carry:
5056   
5057   /****************************************************
5058    * now CARRY contains the result of the comparison: *
5059    * SUBWF sets CARRY iff                             *
5060    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5061    * (F=left, W=right)                                *
5062    ****************************************************/
5063
5064   if (performedLt) {
5065     if (result && AOP_TYPE(result) != AOP_CRY) {
5066       // value will be stored
5067       emitTOGC;
5068     } else {
5069       // value wil only be used in the following genSkipc()
5070       rIfx.condition ^= 1;
5071     }
5072   } // if
5073
5074 correct_result_in_carry:
5075
5076   // assign result to variable (if neccessary)
5077   if (result && AOP_TYPE(result) != AOP_CRY) {
5078     //DEBUGpc ("assign result");
5079     size = AOP_SIZE(result);
5080     while (size--) {
5081       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5082     } // while
5083     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5084   } // if (result)
5085
5086   // perform conditional jump
5087   if (ifx) {
5088     //DEBUGpc ("generate control flow");
5089     genSkipc (&rIfx);
5090     ifx->generated = 1;
5091   } // if
5092 }
5093
5094 #elif 1         /* } */
5095                 /* { */
5096       /* original code */
5097 static void genCmp (operand *left,operand *right,
5098                     operand *result, iCode *ifx, int sign)
5099 {
5100   int size; //, offset = 0 ;
5101   unsigned long lit = 0L,i = 0;
5102   resolvedIfx rFalseIfx;
5103   //  resolvedIfx rTrueIfx;
5104   symbol *truelbl;
5105   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5106 /*
5107   if(ifx) {
5108     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5109     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5110   }
5111 */
5112
5113   FENTRY;
5114   
5115   resolveIfx(&rFalseIfx,ifx);
5116   truelbl  = newiTempLabel(NULL);
5117   size = max(AOP_SIZE(left),AOP_SIZE(right));
5118
5119   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5120
5121 #define _swapp
5122
5123   /* if literal is on the right then swap with left */
5124   if ((AOP_TYPE(right) == AOP_LIT)) {
5125     operand *tmp = right ;
5126     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5127     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5128 #ifdef _swapp
5129
5130     lit = (lit - 1) & mask;
5131     right = left;
5132     left = tmp;
5133     rFalseIfx.condition ^= 1;
5134 #endif
5135
5136   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5137     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5138   }
5139
5140
5141   //if(IC_TRUE(ifx) == NULL)
5142   /* if left & right are bit variables */
5143   if (AOP_TYPE(left) == AOP_CRY &&
5144       AOP_TYPE(right) == AOP_CRY ) {
5145     assert (0 && "bit variables used in genCmp");
5146     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5147     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5148   } else {
5149     /* subtract right from left if at the
5150        end the carry flag is set then we know that
5151        left is greater than right */
5152
5153     symbol *lbl  = newiTempLabel(NULL);
5154
5155 #if 0
5156         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5157                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5158 #endif
5159
5160 #ifndef _swapp
5161     if(AOP_TYPE(right) == AOP_LIT) {
5162
5163       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5164
5165       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5166
5167       /* special cases */
5168
5169       if(lit == 0) {
5170
5171         if(sign != 0) 
5172           genSkipCond(&rFalseIfx,left,size-1,7);
5173         else 
5174           /* no need to compare to 0...*/
5175           /* NOTE: this is a de-generate compare that most certainly 
5176            *       creates some dead code. */
5177           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5178
5179         if(ifx) ifx->generated = 1;
5180         return;
5181
5182       }
5183       size--;
5184
5185       if(size == 0) {
5186         //i = (lit >> (size*8)) & 0xff;
5187         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5188         
5189         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5190
5191         i = ((0-lit) & 0xff);
5192         if(sign) {
5193           if( i == 0x81) { 
5194             /* lit is 0x7f, all signed chars are less than
5195              * this except for 0x7f itself */
5196             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5197             genSkipz2(&rFalseIfx,0);
5198           } else {
5199             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5200             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5201             genSkipc(&rFalseIfx);
5202           }
5203
5204         } else {
5205           if(lit == 1) {
5206             genSkipz2(&rFalseIfx,1);
5207           } else {
5208             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5209             genSkipc(&rFalseIfx);
5210           }
5211         }
5212
5213         if(ifx) ifx->generated = 1;
5214         return;
5215       }
5216
5217       /* chars are out of the way. now do ints and longs */
5218
5219
5220       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5221         
5222       /* special cases */
5223
5224       if(sign) {
5225
5226         if(lit == 0) {
5227           genSkipCond(&rFalseIfx,left,size,7);
5228           if(ifx) ifx->generated = 1;
5229           return;
5230         }
5231
5232         if(lit <0x100) {
5233           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5234
5235           //rFalseIfx.condition ^= 1;
5236           //genSkipCond(&rFalseIfx,left,size,7);
5237           //rFalseIfx.condition ^= 1;
5238
5239           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5240           if(rFalseIfx.condition)
5241             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5242           else
5243             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5244
5245           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5246           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5247           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5248
5249           while(size > 1)
5250             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5251
5252           if(rFalseIfx.condition) {
5253             emitSKPZ;
5254             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5255
5256           } else {
5257             emitSKPNZ;
5258           }
5259
5260           genSkipc(&rFalseIfx);
5261           pic16_emitpLabel(truelbl->key);
5262           if(ifx) ifx->generated = 1;
5263           return;
5264
5265         }
5266
5267         if(size == 1) {
5268
5269           if( (lit & 0xff) == 0) {
5270             /* lower byte is zero */
5271             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5272             i = ((lit >> 8) & 0xff) ^0x80;
5273             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5274             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5275             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5276             genSkipc(&rFalseIfx);
5277
5278
5279             if(ifx) ifx->generated = 1;
5280             return;
5281
5282           }
5283         } else {
5284           /* Special cases for signed longs */
5285           if( (lit & 0xffffff) == 0) {
5286             /* lower byte is zero */
5287             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5288             i = ((lit >> 8*3) & 0xff) ^0x80;
5289             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5290             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5291             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5292             genSkipc(&rFalseIfx);
5293
5294
5295             if(ifx) ifx->generated = 1;
5296             return;
5297
5298           }
5299
5300         }
5301
5302
5303         if(lit & (0x80 << (size*8))) {
5304           /* lit is negative */
5305           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5306
5307           //genSkipCond(&rFalseIfx,left,size,7);
5308
5309           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5310
5311           if(rFalseIfx.condition)
5312             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5313           else
5314             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5315
5316
5317         } else {
5318           /* lit is positive */
5319           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5320           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5321           if(rFalseIfx.condition)
5322             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5323           else
5324             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5325
5326         }
5327
5328         /*
5329           This works, but is only good for ints.
5330           It also requires a "known zero" register.
5331           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5332           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5333           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5334           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5335           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5336           genSkipc(&rFalseIfx);
5337
5338           pic16_emitpLabel(truelbl->key);
5339           if(ifx) ifx->generated = 1;
5340           return;
5341         **/
5342           
5343         /* There are no more special cases, so perform a general compare */
5344   
5345         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5346         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5347
5348         while(size--) {
5349
5350           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5351           emitSKPNZ;
5352           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5353         }
5354         //rFalseIfx.condition ^= 1;
5355         genSkipc(&rFalseIfx);
5356
5357         pic16_emitpLabel(truelbl->key);
5358
5359         if(ifx) ifx->generated = 1;
5360         return;
5361
5362
5363       }
5364
5365
5366       /* sign is out of the way. So now do an unsigned compare */
5367       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5368
5369
5370       /* General case - compare to an unsigned literal on the right.*/
5371
5372       i = (lit >> (size*8)) & 0xff;
5373       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5374       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5375       while(size--) {
5376         i = (lit >> (size*8)) & 0xff;
5377
5378         if(i) {
5379           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5380           emitSKPNZ;
5381           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5382         } else {
5383           /* this byte of the lit is zero, 
5384            *if it's not the last then OR in the variable */
5385           if(size)
5386             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5387         }
5388       }
5389
5390
5391       pic16_emitpLabel(lbl->key);
5392 //      pic16_emitpLabel(truelbl->key);
5393       //if(emitFinalCheck)
5394       genSkipc(&rFalseIfx);
5395       if(sign)
5396         pic16_emitpLabel(truelbl->key);
5397
5398       if(ifx) ifx->generated = 1;
5399       return;
5400
5401
5402     }
5403 #endif  // _swapp
5404
5405     if(AOP_TYPE(left) == AOP_LIT) {
5406       //symbol *lbl = newiTempLabel(NULL);
5407
5408       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5409
5410
5411       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5412
5413       /* Special cases */
5414       if((lit == 0) && (sign == 0)){
5415
5416         size--;
5417         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5418         while(size) 
5419           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5420
5421         genSkipz2(&rFalseIfx,0);
5422         if(ifx) ifx->generated = 1;
5423         return;
5424       }
5425
5426       if(size==1) {
5427         /* Special cases */
5428         lit &= 0xff;
5429         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5430           /* degenerate compare can never be true */
5431           if(rFalseIfx.condition == 0)
5432             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5433
5434           if(ifx) ifx->generated = 1;
5435           return;
5436         }
5437
5438         if(sign) {
5439           /* signed comparisons to a literal byte */
5440
5441           int lp1 = (lit+1) & 0xff;
5442
5443           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5444           switch (lp1) {
5445           case 0:
5446             rFalseIfx.condition ^= 1;
5447             genSkipCond(&rFalseIfx,right,0,7);
5448             break;
5449           case 0x7f:
5450             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5451             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5452             genSkipz2(&rFalseIfx,1);
5453             break;
5454           default:
5455             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5456             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5457             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5458             rFalseIfx.condition ^= 1;
5459             genSkipc(&rFalseIfx);
5460             break;
5461           }
5462         } else {
5463           /* unsigned comparisons to a literal byte */
5464
5465           switch(lit & 0xff ) {
5466           case 0:
5467             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5468             genSkipz2(&rFalseIfx,0);
5469             break;
5470           case 0x7f:
5471             rFalseIfx.condition ^= 1;
5472             genSkipCond(&rFalseIfx,right,0,7);
5473             break;
5474
5475           default:
5476             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5477             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5478             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5479             rFalseIfx.condition ^= 1;
5480             if (AOP_TYPE(result) == AOP_CRY)
5481               genSkipc(&rFalseIfx);
5482             else {
5483               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5484               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5485             }         
5486             break;
5487           }
5488         }
5489
5490         if(ifx) ifx->generated = 1;
5491         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5492                 goto check_carry;
5493         return;
5494
5495       } else {
5496
5497         /* Size is greater than 1 */
5498
5499         if(sign) {
5500           int lp1 = lit+1;
5501
5502           size--;
5503
5504           if(lp1 == 0) {
5505             /* this means lit = 0xffffffff, or -1 */
5506
5507
5508             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5509             rFalseIfx.condition ^= 1;
5510             genSkipCond(&rFalseIfx,right,size,7);
5511             if(ifx) ifx->generated = 1;
5512
5513             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5514               goto check_carry;
5515
5516             return;
5517           }
5518
5519           if(lit == 0) {
5520             int s = size;
5521
5522             if(rFalseIfx.condition) {
5523               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5524               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5525             }
5526
5527             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5528             while(size--)
5529               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5530
5531
5532             emitSKPZ;
5533             if(rFalseIfx.condition) {
5534               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5535               pic16_emitpLabel(truelbl->key);
5536             }else {
5537               rFalseIfx.condition ^= 1;
5538               genSkipCond(&rFalseIfx,right,s,7);
5539             }
5540
5541             if(ifx) ifx->generated = 1;
5542
5543             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5544               goto check_carry;
5545
5546             return;
5547           }
5548
5549           if((size == 1) &&  (0 == (lp1&0xff))) {
5550             /* lower byte of signed word is zero */
5551             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5552             i = ((lp1 >> 8) & 0xff) ^0x80;
5553             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5554             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5555             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5556
5557             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5558               emitTOGC;
5559               if(ifx) ifx->generated = 1;
5560               goto check_carry;
5561             } else {
5562               rFalseIfx.condition ^= 1;
5563               genSkipc(&rFalseIfx);
5564               if(ifx) ifx->generated = 1;
5565             }
5566
5567             return;
5568           }
5569
5570           if(lit & (0x80 << (size*8))) {
5571             /* Lit is less than zero */
5572             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5573             //rFalseIfx.condition ^= 1;
5574             //genSkipCond(&rFalseIfx,left,size,7);
5575             //rFalseIfx.condition ^= 1;
5576             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5577             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5578
5579             if(rFalseIfx.condition)
5580               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5581             else
5582               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5583
5584
5585           } else {
5586             /* Lit is greater than or equal to zero */
5587             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5588             //rFalseIfx.condition ^= 1;
5589             //genSkipCond(&rFalseIfx,right,size,7);
5590             //rFalseIfx.condition ^= 1;
5591
5592             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5593             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5594
5595             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5596             if(rFalseIfx.condition)
5597               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5598             else
5599               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5600
5601           }
5602
5603           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5604           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5605
5606           while(size--) {
5607
5608             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5609             emitSKPNZ;
5610             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5611           }
5612           rFalseIfx.condition ^= 1;
5613           //rFalseIfx.condition = 1;
5614           genSkipc(&rFalseIfx);
5615
5616           pic16_emitpLabel(truelbl->key);
5617
5618           if(ifx) ifx->generated = 1;
5619
5620
5621           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5622             goto check_carry;
5623
5624           return;
5625           // end of if (sign)
5626         } else {
5627
5628           /* compare word or long to an unsigned literal on the right.*/
5629
5630
5631           size--;
5632           if(lit < 0xff) {
5633             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5634             switch (lit) {
5635             case 0:
5636               break; /* handled above */
5637 /*
5638             case 0xff:
5639               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5640               while(size--)
5641                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5642               genSkipz2(&rFalseIfx,0);
5643               break;
5644 */
5645             default:
5646               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5647               while(--size)
5648                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5649
5650               emitSKPZ;
5651               if(rFalseIfx.condition)
5652                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5653               else
5654                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5655
5656
5657               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5658               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5659
5660               rFalseIfx.condition ^= 1;
5661               genSkipc(&rFalseIfx);
5662             }
5663
5664             pic16_emitpLabel(truelbl->key);
5665
5666             if(ifx) ifx->generated = 1;
5667
5668             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5669               goto check_carry;
5670
5671             return;
5672           }
5673
5674
5675           lit++;
5676           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5677           i = (lit >> (size*8)) & 0xff;
5678
5679           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5680           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5681
5682           while(size--) {
5683             i = (lit >> (size*8)) & 0xff;
5684
5685             if(i) {
5686               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5687               emitSKPNZ;
5688               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5689             } else {
5690               /* this byte of the lit is zero, 
5691                * if it's not the last then OR in the variable */
5692               if(size)
5693                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5694             }
5695           }
5696
5697
5698           pic16_emitpLabel(lbl->key);
5699
5700           rFalseIfx.condition ^= 1;
5701
5702           genSkipc(&rFalseIfx);
5703         }
5704
5705         if(sign)
5706           pic16_emitpLabel(truelbl->key);
5707         if(ifx) ifx->generated = 1;
5708
5709             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5710               goto check_carry;
5711
5712         return;
5713       }
5714     }
5715     /* Compare two variables */
5716
5717     DEBUGpic16_emitcode(";sign","%d",sign);
5718
5719     size--;
5720     if(sign) {
5721       /* Sigh. thus sucks... */
5722       if(size) {
5723         pCodeOp *pctemp;
5724         
5725         pctemp = pic16_popGetTempReg(1);
5726         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5727         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5728         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5729         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5730         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5731         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5732         pic16_popReleaseTempReg(pctemp, 1);
5733       } else {
5734         /* Signed char comparison */
5735         /* Special thanks to Nikolai Golovchenko for this snippet */
5736         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5737         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5738         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5739         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5740         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5741         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5742
5743         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5744         genSkipc(&rFalseIfx);
5745           
5746         if(ifx) ifx->generated = 1;
5747
5748             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5749               goto check_carry;
5750
5751         return;
5752       }
5753
5754     } else {
5755
5756       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5757       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5758     }
5759
5760
5761     /* The rest of the bytes of a multi-byte compare */
5762     while (size) {
5763
5764       emitSKPZ;
5765       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5766       size--;
5767
5768       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5769       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5770
5771
5772     }
5773
5774     pic16_emitpLabel(lbl->key);
5775
5776     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5777     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5778         (AOP_TYPE(result) == AOP_REG)) {
5779       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5780       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5781     } else {
5782       genSkipc(&rFalseIfx);
5783     }         
5784     //genSkipc(&rFalseIfx);
5785     if(ifx) ifx->generated = 1;
5786
5787
5788             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5789               goto check_carry;
5790
5791     return;
5792
5793   }
5794
5795 check_carry:
5796   if ((AOP_TYPE(result) != AOP_CRY) 
5797         && AOP_SIZE(result)) {
5798     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5799
5800     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5801
5802     pic16_outBitC(result);
5803   } else {
5804     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5805     /* if the result is used in the next
5806        ifx conditional branch then generate
5807        code a little differently */
5808     if (ifx )
5809       genIfxJump (ifx,"c");
5810     else
5811       pic16_outBitC(result);
5812     /* leave the result in acc */
5813   }
5814
5815 }
5816
5817 #elif 0 /* VR version of genCmp() */    /* } else { */
5818
5819 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5820 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5821         operand *result, int offset, int invert_op)
5822 {
5823   /* add code here */
5824   
5825   /* check condition, > or < ?? */
5826   if(rIfx->condition != 0)invert_op ^= 1;
5827   
5828   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5829
5830   if(!ifx)invert_op ^= 1;
5831
5832   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5833       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5834   
5835   /* do selection */
5836   if(!invert_op)return POC_CPFSGT;
5837   else return POC_CPFSLT;
5838 }
5839
5840 static int compareAopfirstpass=1;
5841
5842 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5843             operand *oper, int offset, operand *result,
5844             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5845             symbol *tlbl)
5846 {
5847   int op;
5848   symbol *truelbl;
5849
5850   /* invert if there is a result to be loaded, in order to fit,
5851    * SETC/CLRC sequence */
5852   if(AOP_SIZE(result))invert_op ^= 1;
5853
5854 //  if(sign && !offset)invert_op ^= 1;
5855   
5856 //  if(sign)invert_op ^= 1;
5857   
5858   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5859
5860   if(AOP_SIZE(result) && compareAopfirstpass) {
5861     if(!ifx) {
5862       if(pcop2)
5863         pic16_emitpcode(POC_SETF, pcop2);
5864       else
5865         emitSETC;
5866     } else {
5867       if(pcop2)
5868         pic16_emitpcode(POC_CLRF, pcop2);
5869       else
5870         emitCLRC;
5871     }
5872   }
5873
5874   compareAopfirstpass = 0;
5875
5876       /* there is a bug when comparing operands with size > 1,
5877        * because higher bytes can be equal and test should be performed
5878        * to the next lower byte, current algorithm, considers operands
5879        * inequal in these cases! -- VR 20041107 */
5880
5881     
5882   if(pcop)
5883     pic16_emitpcode(op, pcop);
5884   else
5885     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5886
5887
5888   if((!sign || !offset) && AOP_SIZE(result)) {
5889     if(!ifx) {
5890       if(pcop2)
5891         pic16_emitpcode(POC_CLRF, pcop2);
5892         else
5893         emitCLRC;
5894     } else {
5895       if(pcop2)
5896         pic16_emitpcode(POC_SETF, pcop2);
5897       else
5898         emitSETC;
5899     }
5900     
5901     /* don't emit final branch (offset == 0) */
5902     if(offset) {
5903
5904       if(pcop2)
5905         pic16_emitpcode(POC_RRCF, pcop2);
5906
5907       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5908     }
5909   } else {
5910     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5911       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5912             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5913
5914       truelbl = newiTempLabel( NULL );
5915       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5916       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5917         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5918       else
5919         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5920       pic16_emitpLabel(truelbl->key);
5921     } else {
5922       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5923     }
5924   }
5925 }
5926
5927 static void genCmp (operand *left, operand *right,
5928                     operand *result, iCode *ifx, int sign)
5929 {
5930   int size, cmpop=1;
5931   long lit = 0L;
5932   resolvedIfx rFalseIfx;
5933   symbol *falselbl, *tlbl;
5934
5935     FENTRY;
5936     
5937     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5938
5939     resolveIfx(&rFalseIfx, ifx);
5940     size = max(AOP_SIZE(left), AOP_SIZE(right));
5941     
5942     /* if left & right are bit variables */
5943     if(AOP_TYPE(left) == AOP_CRY
5944       && AOP_TYPE(right) == AOP_CRY ) {
5945
5946         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5947         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5948         
5949         werror(W_POSSBUG2, __FILE__, __LINE__);
5950         exit(-1);
5951     }
5952     
5953     /* if literal is on the right then swap with left */
5954     if((AOP_TYPE(right) == AOP_LIT)) {
5955       operand *tmp = right ;
5956 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
5957
5958         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5959
5960 //      lit = (lit - 1) & mask;
5961         right = left;
5962         left = tmp;
5963         rFalseIfx.condition ^= 1;               /* reverse compare */
5964     } else
5965     if ((AOP_TYPE(left) == AOP_LIT)) {
5966       /* float compares are handled by support functions */
5967       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5968     }
5969
5970     /* actual comparing algorithm */
5971 //    size = AOP_SIZE( right );
5972
5973     falselbl = newiTempLabel( NULL );
5974     if(AOP_TYPE(left) == AOP_LIT) {
5975       /* compare to literal */
5976       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5977       
5978       if(sign) {
5979         pCodeOp *pct, *pct2;
5980         symbol *tlbl1;
5981
5982         /* signed compare */
5983         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5984
5985         pct = pic16_popCopyReg(&pic16_pc_prodl);
5986         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5987         tlbl = newiTempLabel( NULL );
5988         
5989         /* first compare signs:
5990          *  a. if both are positive, compare just like unsigned
5991          *  b. if both are negative, invert cmpop, compare just like unsigned
5992          *  c. if different signs, determine the result directly */
5993
5994         size--;
5995
5996 #if 1
5997         /* { */
5998         tlbl1 = newiTempLabel( NULL );
5999 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6000
6001         if(lit > 0) {
6002
6003           /* literal is zero or positive:
6004            *  a. if carry is zero, too, continue compare,
6005            *  b. if carry is set, then continue depending on cmpop ^ condition:
6006            *    1. '<' return false (literal < variable),
6007            *    2. '>' return true (literal > variable) */
6008 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6009           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6010           
6011           
6012           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6013           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6014         } else 
6015         if(lit < 0) {
6016           
6017           /* literal is negative:
6018            *  a. if carry is set, too, continue compare,
6019            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6020            *    1. '<' return true (literal < variable),
6021            *    2. '>' return false (literal > variable) */
6022 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6023           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6024           
6025           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6026           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6027         }
6028 #if 1
6029         else {
6030           /* lit == 0 */
6031           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6032           
6033           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6034           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6035         }
6036 #endif
6037         
6038         
6039         pic16_emitpLabel( tlbl1->key );
6040 #endif  /* } */
6041
6042         compareAopfirstpass=1;
6043 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6044 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6045 //        pic16_emitpcode(POC_MOVWF, pct);
6046
6047 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6048         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6049 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6050         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6051
6052         /* generic case */        
6053           while( size-- ) {
6054 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6055 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6056 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6057 //            pic16_emitpcode(POC_MOVWF, pct);
6058
6059 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6060             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6061             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6062 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6063 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6064           }
6065         
6066         if(ifx)ifx->generated = 1;
6067
6068         if(AOP_SIZE(result)) {
6069           pic16_emitpLabel(tlbl->key);
6070           pic16_emitpLabel(falselbl->key);
6071           pic16_outBitOp( result, pct2 );
6072         } else {
6073           pic16_emitpLabel(tlbl->key);
6074         }
6075       } else {
6076
6077         /* unsigned compare */      
6078         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6079     
6080         compareAopfirstpass=1;
6081         while(size--) {
6082           
6083           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6084           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6085
6086         }
6087         if(ifx)ifx->generated = 1;
6088
6089         if(AOP_SIZE(result)) {
6090           pic16_emitpLabel(falselbl->key);
6091           pic16_outBitC( result );
6092         }
6093
6094       }
6095     } else {
6096       /* compare registers */
6097       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6098
6099
6100       if(sign) {
6101         pCodeOp *pct, *pct2;
6102         
6103         /* signed compare */
6104         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6105
6106         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6107         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6108         tlbl = newiTempLabel( NULL );
6109         
6110         compareAopfirstpass=1;
6111
6112         size--;
6113         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6114 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6115         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6116         pic16_emitpcode(POC_MOVWF, pct);
6117
6118         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6119 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6120         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6121
6122         /* WREG already holds left + 0x80 */
6123         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6124         
6125         while( size-- ) {
6126           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6127 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6128           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6129           pic16_emitpcode(POC_MOVWF, pct);
6130                 
6131           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6132 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6133           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6134
6135           /* WREG already holds left + 0x80 */
6136           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6137 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6138         }
6139         
6140         if(ifx)ifx->generated = 1;
6141
6142         if(AOP_SIZE(result)) {
6143           pic16_emitpLabel(tlbl->key);
6144           pic16_emitpLabel(falselbl->key);
6145           pic16_outBitOp( result, pct2 );
6146         } else {
6147           pic16_emitpLabel(tlbl->key);
6148         }
6149
6150       } else {
6151         /* unsigned compare */      
6152         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6153
6154         compareAopfirstpass=1;
6155         while(size--) {
6156           
6157           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6158           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6159
6160         }
6161
6162         if(ifx)ifx->generated = 1;
6163         if(AOP_SIZE(result)) {
6164
6165           pic16_emitpLabel(falselbl->key);
6166           pic16_outBitC( result );
6167         }
6168
6169       }
6170     }
6171 }
6172
6173 #endif  /* } */
6174
6175
6176
6177 /*-----------------------------------------------------------------*/
6178 /* genCmpGt :- greater than comparison                             */
6179 /*-----------------------------------------------------------------*/
6180 static void genCmpGt (iCode *ic, iCode *ifx)
6181 {
6182   operand *left, *right, *result;
6183   sym_link *letype , *retype;
6184   int sign ;
6185
6186     FENTRY;
6187     
6188     left = IC_LEFT(ic);
6189     right= IC_RIGHT(ic);
6190     result = IC_RESULT(ic);
6191
6192     letype = getSpec(operandType(left));
6193     retype =getSpec(operandType(right));
6194     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6195     /* assign the amsops */
6196     pic16_aopOp (left,ic,FALSE);
6197     pic16_aopOp (right,ic,FALSE);
6198     pic16_aopOp (result,ic,TRUE);
6199
6200     genCmp(right, left, result, ifx, sign);
6201
6202     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6203     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6204     pic16_freeAsmop(result,NULL,ic,TRUE); 
6205 }
6206
6207 /*-----------------------------------------------------------------*/
6208 /* genCmpLt - less than comparisons                                */
6209 /*-----------------------------------------------------------------*/
6210 static void genCmpLt (iCode *ic, iCode *ifx)
6211 {
6212   operand *left, *right, *result;
6213   sym_link *letype , *retype;
6214   int sign ;
6215
6216     FENTRY;
6217
6218     left = IC_LEFT(ic);
6219     right= IC_RIGHT(ic);
6220     result = IC_RESULT(ic);
6221
6222     letype = getSpec(operandType(left));
6223     retype =getSpec(operandType(right));
6224     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6225
6226     /* assign the amsops */
6227     pic16_aopOp (left,ic,FALSE);
6228     pic16_aopOp (right,ic,FALSE);
6229     pic16_aopOp (result,ic,TRUE);
6230
6231     genCmp(left, right, result, ifx, sign);
6232
6233     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6234     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6235     pic16_freeAsmop(result,NULL,ic,TRUE); 
6236 }
6237
6238 #if 0
6239 // not needed ATM
6240 // FIXME reenable literal optimisation when the pic16 port is stable
6241
6242 /*-----------------------------------------------------------------*/
6243 /* genc16bit2lit - compare a 16 bit value to a literal             */
6244 /*-----------------------------------------------------------------*/
6245 static void genc16bit2lit(operand *op, int lit, int offset)
6246 {
6247   int i;
6248
6249   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6250   if( (lit&0xff) == 0) 
6251     i=1;
6252   else
6253     i=0;
6254
6255   switch( BYTEofLONG(lit,i)) { 
6256   case 0:
6257     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6258     break;
6259   case 1:
6260     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6261     break;
6262   case 0xff:
6263     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6264     break;
6265   default:
6266     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6267     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6268   }
6269
6270   i ^= 1;
6271
6272   switch( BYTEofLONG(lit,i)) { 
6273   case 0:
6274     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6275     break;
6276   case 1:
6277     emitSKPNZ;
6278     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6279     break;
6280   case 0xff:
6281     emitSKPNZ;
6282     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6283     break;
6284   default:
6285     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6286     emitSKPNZ;
6287     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6288
6289   }
6290
6291 }
6292 #endif
6293
6294 #if 0
6295 // not needed ATM
6296 /*-----------------------------------------------------------------*/
6297 /* gencjneshort - compare and jump if not equal                    */
6298 /*-----------------------------------------------------------------*/
6299 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6300 {
6301   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6302   int offset = 0;
6303   int res_offset = 0;  /* the result may be a different size then left or right */
6304   int res_size = AOP_SIZE(result);
6305   resolvedIfx rIfx;
6306   symbol *lbl, *lbl_done;
6307
6308   unsigned long lit = 0L;
6309   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6310
6311   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6312   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6313   if(result)
6314     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6315   resolveIfx(&rIfx,ifx);
6316   lbl =  newiTempLabel(NULL);
6317   lbl_done =  newiTempLabel(NULL);
6318
6319
6320   /* if the left side is a literal or 
6321      if the right is in a pointer register and left 
6322      is not */
6323   if ((AOP_TYPE(left) == AOP_LIT) || 
6324       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6325     operand *t = right;
6326     right = left;
6327     left = t;
6328   }
6329   if(AOP_TYPE(right) == AOP_LIT)
6330     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6331
6332   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6333     preserve_result = 1;
6334
6335   if(result && !preserve_result)
6336     {
6337       int i;
6338       for(i = 0; i < AOP_SIZE(result); i++)
6339         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6340     }
6341
6342
6343   /* if the right side is a literal then anything goes */
6344   if (AOP_TYPE(right) == AOP_LIT &&
6345       AOP_TYPE(left) != AOP_DIR ) {
6346     switch(size) {
6347     case 2:
6348       genc16bit2lit(left, lit, 0);
6349       emitSKPZ;
6350       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6351       break;
6352     default:
6353       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6354       while (size--) {
6355         if(lit & 0xff) {
6356           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6357           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6358         } else {
6359           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6360         }
6361
6362         emitSKPZ;
6363         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6364         offset++;
6365         if(res_offset < res_size-1)
6366           res_offset++;
6367         lit >>= 8;
6368       }
6369       break;
6370     }
6371   }
6372
6373   /* if the right side is in a register or in direct space or
6374      if the left is a pointer register & right is not */    
6375   else if (AOP_TYPE(right) == AOP_REG ||
6376            AOP_TYPE(right) == AOP_DIR || 
6377            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6378            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6379     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6380     int lbl_key = lbl->key;
6381
6382     if(result) {
6383       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6384       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6385     }else {
6386       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6387       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6388               __FUNCTION__,__LINE__);
6389       return;
6390     }
6391    
6392 /*     switch(size) { */
6393 /*     case 2: */
6394 /*       genc16bit2lit(left, lit, 0); */
6395 /*       emitSKPNZ; */
6396 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6397 /*       break; */
6398 /*     default: */
6399     while (size--) {
6400       int emit_skip=1;
6401       if((AOP_TYPE(left) == AOP_DIR) && 
6402          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6403
6404         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6405         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6406
6407       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6408             
6409         switch (lit & 0xff) {
6410         case 0:
6411           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6412           break;
6413         case 1:
6414           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6415           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6416           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6417           emit_skip=0;
6418           break;
6419         case 0xff:
6420           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6421           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6422           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6423           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6424           emit_skip=0;
6425           break;
6426         default:
6427           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6428           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6429         }
6430         lit >>= 8;
6431
6432       } else {
6433         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6434       }
6435       if(emit_skip) {
6436         if(AOP_TYPE(result) == AOP_CRY) {
6437           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6438           if(rIfx.condition)
6439             emitSKPNZ;
6440           else
6441             emitSKPZ;
6442           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6443         } else {
6444           /* fix me. probably need to check result size too */
6445           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6446           if(rIfx.condition)
6447             emitSKPZ;
6448           else
6449             emitSKPNZ;
6450           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6451           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6452         }
6453         if(ifx)
6454           ifx->generated=1;
6455       }
6456       emit_skip++;
6457       offset++;
6458       if(res_offset < res_size-1)
6459         res_offset++;
6460     }
6461 /*       break; */
6462 /*     } */
6463   } else if(AOP_TYPE(right) == AOP_REG &&
6464             AOP_TYPE(left) != AOP_DIR){
6465
6466     while(size--) {
6467       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6468       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6469       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6470       if(rIfx.condition)
6471         emitSKPNZ;
6472       else
6473         emitSKPZ;
6474       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6475       offset++;
6476       if(res_offset < res_size-1)
6477         res_offset++;
6478     }
6479       
6480   }else{
6481     /* right is a pointer reg need both a & b */
6482     while(size--) {
6483       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6484       if(strcmp(l,"b"))
6485         pic16_emitcode("mov","b,%s",l);
6486       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6487       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6488       offset++;
6489     }
6490   }
6491
6492   if(result && preserve_result)
6493     {
6494       int i;
6495       for(i = 0; i < AOP_SIZE(result); i++)
6496         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6497     }
6498
6499   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6500
6501   if(result && preserve_result)
6502     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6503
6504   if(!rIfx.condition)
6505     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6506
6507   pic16_emitpLabel(lbl->key);
6508
6509   if(result && preserve_result)
6510     {
6511       int i;
6512       for(i = 0; i < AOP_SIZE(result); i++)
6513         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6514
6515       pic16_emitpLabel(lbl_done->key);
6516    }
6517
6518   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6519
6520   if(ifx)
6521     ifx->generated = 1;
6522 }
6523 #endif
6524
6525 #if 0
6526 /*-----------------------------------------------------------------*/
6527 /* gencjne - compare and jump if not equal                         */
6528 /*-----------------------------------------------------------------*/
6529 static void gencjne(operand *left, operand *right, iCode *ifx)
6530 {
6531     symbol *tlbl  = newiTempLabel(NULL);
6532
6533     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6534     gencjneshort(left, right, lbl);
6535
6536     pic16_emitcode("mov","a,%s",one);
6537     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6538     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6539     pic16_emitcode("clr","a");
6540     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6541
6542     pic16_emitpLabel(lbl->key);
6543     pic16_emitpLabel(tlbl->key);
6544
6545 }
6546 #endif
6547
6548
6549 /*-----------------------------------------------------------------*/
6550 /* is_LitOp - check if operand has to be treated as literal        */
6551 /*-----------------------------------------------------------------*/
6552 static bool is_LitOp(operand *op)
6553 {
6554   return ((AOP_TYPE(op) == AOP_LIT)
6555       || ( (AOP_TYPE(op) == AOP_PCODE)
6556           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6557               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6558 }
6559
6560 /*-----------------------------------------------------------------*/
6561 /* is_LitAOp - check if operand has to be treated as literal        */
6562 /*-----------------------------------------------------------------*/
6563 static bool is_LitAOp(asmop *aop)
6564 {
6565   return ((aop->type == AOP_LIT)
6566       || ( (aop->type == AOP_PCODE)
6567           && ( (aop->aopu.pcop->type == PO_LITERAL)
6568               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6569 }
6570
6571
6572
6573 /*-----------------------------------------------------------------*/
6574 /* genCmpEq - generates code for equal to                          */
6575 /*-----------------------------------------------------------------*/
6576 static void genCmpEq (iCode *ic, iCode *ifx)
6577 {
6578   operand *left, *right, *result;
6579   symbol *falselbl = newiTempLabel(NULL);
6580   symbol *donelbl = newiTempLabel(NULL);
6581
6582   int preserve_result = 0;
6583   int generate_result = 0;
6584   int i=0;
6585   unsigned long lit = -1;
6586
6587   FENTRY;
6588   
6589   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6590   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6591   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6592  
6593   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6594
6595   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6596     {
6597       werror(W_POSSBUG2, __FILE__, __LINE__);
6598       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6599       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6600       goto release;
6601     }
6602
6603   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6604     {
6605       operand *tmp = right ;
6606       right = left;
6607       left = tmp;
6608     }
6609
6610   if (AOP_TYPE(right) == AOP_LIT) {
6611     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6612   }
6613
6614   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6615     preserve_result = 1;
6616
6617   if(result && AOP_SIZE(result))
6618     generate_result = 1;
6619
6620   if(generate_result && !preserve_result)
6621     {
6622       for(i = 0; i < AOP_SIZE(result); i++)
6623         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6624     }
6625
6626   assert( AOP_SIZE(left) == AOP_SIZE(right) );
6627   for(i=0; i < AOP_SIZE(left); i++)
6628     {
6629       if(AOP_TYPE(left) != AOP_ACC)
6630         {
6631           if(is_LitOp(left))
6632             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6633           else
6634             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6635         }
6636       if(is_LitOp(right)) {
6637         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6638           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6639         }
6640       } else
6641         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6642
6643       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6644     }
6645
6646   // result == true
6647
6648   if(generate_result && preserve_result)
6649     {
6650       for(i = 0; i < AOP_SIZE(result); i++)
6651         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6652     }
6653
6654   if(generate_result)
6655     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6656
6657   if(generate_result && preserve_result)
6658     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6659
6660   if(ifx && IC_TRUE(ifx))
6661     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6662
6663   if(ifx && IC_FALSE(ifx))
6664     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6665
6666   pic16_emitpLabel(falselbl->key);
6667
6668   // result == false
6669
6670   if(ifx && IC_FALSE(ifx))
6671     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6672
6673   if(generate_result && preserve_result)
6674     {
6675       for(i = 0; i < AOP_SIZE(result); i++)
6676         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6677     }
6678
6679   pic16_emitpLabel(donelbl->key);
6680
6681   if(ifx)
6682     ifx->generated = 1;
6683
6684 release:
6685   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6686   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6687   pic16_freeAsmop(result,NULL,ic,TRUE);
6688
6689 }
6690
6691
6692 #if 0
6693 // old version kept for reference
6694
6695 /*-----------------------------------------------------------------*/
6696 /* genCmpEq - generates code for equal to                          */
6697 /*-----------------------------------------------------------------*/
6698 static void genCmpEq (iCode *ic, iCode *ifx)
6699 {
6700     operand *left, *right, *result;
6701     unsigned long lit = 0L;
6702     int size,offset=0;
6703     symbol *falselbl  = newiTempLabel(NULL);
6704
6705
6706     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6707
6708     if(ifx)
6709       DEBUGpic16_emitcode ("; ifx is non-null","");
6710     else
6711       DEBUGpic16_emitcode ("; ifx is null","");
6712
6713     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6714     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6715     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6716
6717     size = max(AOP_SIZE(left),AOP_SIZE(right));
6718
6719     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6720
6721     /* if literal, literal on the right or 
6722     if the right is in a pointer register and left 
6723     is not */
6724     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6725         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6726       operand *tmp = right ;
6727       right = left;
6728       left = tmp;
6729     }
6730
6731
6732     if(ifx && !AOP_SIZE(result)){
6733         symbol *tlbl;
6734         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6735         /* if they are both bit variables */
6736         if (AOP_TYPE(left) == AOP_CRY &&
6737             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6738                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6739             if(AOP_TYPE(right) == AOP_LIT){
6740                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6741                 if(lit == 0L){
6742                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6743                     pic16_emitcode("cpl","c");
6744                 } else if(lit == 1L) {
6745                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6746                 } else {
6747                     pic16_emitcode("clr","c");
6748                 }
6749                 /* AOP_TYPE(right) == AOP_CRY */
6750             } else {
6751                 symbol *lbl = newiTempLabel(NULL);
6752                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6753                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6754                 pic16_emitcode("cpl","c");
6755                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6756             }
6757             /* if true label then we jump if condition
6758             supplied is true */
6759             tlbl = newiTempLabel(NULL);
6760             if ( IC_TRUE(ifx) ) {
6761                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6762                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6763             } else {
6764                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6765                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6766             }
6767             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6768
6769                 {
6770                 /* left and right are both bit variables, result is carry */
6771                         resolvedIfx rIfx;
6772               
6773                         resolveIfx(&rIfx,ifx);
6774
6775                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6776                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6777                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6778                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6779                         genSkipz2(&rIfx,0);
6780                 }
6781         } else {
6782
6783                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6784
6785                         /* They're not both bit variables. Is the right a literal? */
6786                         if(AOP_TYPE(right) == AOP_LIT) {
6787                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6788             
6789                         switch(size) {
6790
6791                                 case 1:
6792                                         switch(lit & 0xff) {
6793                                                 case 1:
6794                                                                 if ( IC_TRUE(ifx) ) {
6795                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6796                                                                         emitSKPNZ;
6797                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6798                                                                 } else {
6799                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6800                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6801                                                                 }
6802                                                                 break;
6803                                                 case 0xff:
6804                                                                 if ( IC_TRUE(ifx) ) {
6805                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6806                                                                         emitSKPNZ;
6807                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6808                                                                 } else {
6809                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6810                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6811                                                                 }
6812                                                                 break;
6813                                                 default:
6814                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6815                                                                 if(lit)
6816                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6817                                                                 genSkip(ifx,'z');
6818                                         } // switch lit
6819
6820
6821                                         /* end of size == 1 */
6822                                         break;
6823               
6824                                 case 2:
6825                                         genc16bit2lit(left,lit,offset);
6826                                         genSkip(ifx,'z');
6827                                         break;
6828                                         /* end of size == 2 */
6829
6830                                 default:
6831                                         /* size is 4 */
6832                                         if(lit==0) {
6833                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6834                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6835                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6836                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6837                                                 genSkip(ifx,'z');
6838                                         } else {
6839                                                 /* search for patterns that can be optimized */
6840
6841                                                 genc16bit2lit(left,lit,0);
6842                                                 lit >>= 16;
6843                                                 if(lit) {
6844                                                                 if(IC_TRUE(ifx))
6845                                                                 emitSKPZ; // if hi word unequal
6846                                                                 else
6847                                                                 emitSKPNZ; // if hi word equal
6848                                                                 // fail early
6849                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6850                                                         genc16bit2lit(left,lit,2);
6851                                                         genSkip(ifx,'z');
6852                                                 } else {
6853                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6854                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6855                                                         genSkip(ifx,'z');
6856                                                 }
6857                                         }
6858                                                 pic16_emitpLabel(falselbl->key);
6859                                                 break;
6860
6861                         } // switch size
6862           
6863                         ifx->generated = 1;
6864                         goto release ;
6865             
6866
6867           } else if(AOP_TYPE(right) == AOP_CRY ) {
6868             /* we know the left is not a bit, but that the right is */
6869             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6870             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6871                       pic16_popGet(AOP(right),offset));
6872             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6873
6874             /* if the two are equal, then W will be 0 and the Z bit is set
6875              * we could test Z now, or go ahead and check the high order bytes if
6876              * the variable we're comparing is larger than a byte. */
6877
6878             while(--size)
6879               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6880
6881             if ( IC_TRUE(ifx) ) {
6882               emitSKPNZ;
6883               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6884               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6885             } else {
6886               emitSKPZ;
6887               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6888               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6889             }
6890
6891           } else {
6892             /* They're both variables that are larger than bits */
6893             int s = size;
6894
6895             tlbl = newiTempLabel(NULL);
6896
6897             while(size--) {
6898               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6899               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6900
6901               if ( IC_TRUE(ifx) ) {
6902                 if(size) {
6903                   emitSKPZ;
6904                 
6905                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6906
6907                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6908                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6909                 } else {
6910                   emitSKPNZ;
6911
6912                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6913
6914
6915                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6916                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6917                 }
6918               } else {
6919                 emitSKPZ;
6920
6921                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6922
6923                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6924                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6925               }
6926               offset++;
6927             }
6928             if(s>1 && IC_TRUE(ifx)) {
6929               pic16_emitpLabel(tlbl->key);
6930               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
6931             }
6932           }
6933         }
6934         /* mark the icode as generated */
6935         ifx->generated = 1;
6936         goto release ;
6937     }
6938
6939     /* if they are both bit variables */
6940     if (AOP_TYPE(left) == AOP_CRY &&
6941         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6942         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
6943         if(AOP_TYPE(right) == AOP_LIT){
6944             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6945             if(lit == 0L){
6946                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6947                 pic16_emitcode("cpl","c");
6948             } else if(lit == 1L) {
6949                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6950             } else {
6951                 pic16_emitcode("clr","c");
6952             }
6953             /* AOP_TYPE(right) == AOP_CRY */
6954         } else {
6955             symbol *lbl = newiTempLabel(NULL);
6956             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6957             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6958             pic16_emitcode("cpl","c");
6959             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6960         }
6961         /* c = 1 if egal */
6962         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6963             pic16_outBitC(result);
6964             goto release ;
6965         }
6966         if (ifx) {
6967             genIfxJump (ifx,"c");
6968             goto release ;
6969         }
6970         /* if the result is used in an arithmetic operation
6971         then put the result in place */
6972         pic16_outBitC(result);
6973     } else {
6974       
6975       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
6976       gencjne(left,right,result,ifx);
6977 /*
6978       if(ifx) 
6979         gencjne(left,right,newiTempLabel(NULL));
6980       else {
6981         if(IC_TRUE(ifx)->key)
6982           gencjne(left,right,IC_TRUE(ifx)->key);
6983         else
6984           gencjne(left,right,IC_FALSE(ifx)->key);
6985         ifx->generated = 1;
6986         goto release ;
6987       }
6988       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6989         pic16_aopPut(AOP(result),"a",0);
6990         goto release ;
6991       }
6992
6993       if (ifx) {
6994         genIfxJump (ifx,"a");
6995         goto release ;
6996       }
6997 */
6998       /* if the result is used in an arithmetic operation
6999          then put the result in place */
7000 /*
7001       if (AOP_TYPE(result) != AOP_CRY) 
7002         pic16_outAcc(result);
7003 */
7004       /* leave the result in acc */
7005     }
7006
7007 release:
7008     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7009     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7010     pic16_freeAsmop(result,NULL,ic,TRUE);
7011 }
7012 #endif
7013
7014 /*-----------------------------------------------------------------*/
7015 /* ifxForOp - returns the icode containing the ifx for operand     */
7016 /*-----------------------------------------------------------------*/
7017 static iCode *ifxForOp ( operand *op, iCode *ic )
7018 {
7019   FENTRY2;
7020
7021     /* if true symbol then needs to be assigned */
7022     if (IS_TRUE_SYMOP(op))
7023         return NULL ;
7024
7025     /* if this has register type condition and
7026     the next instruction is ifx with the same operand
7027     and live to of the operand is upto the ifx only then */
7028     if (ic->next
7029         && ic->next->op == IFX
7030         && IC_COND(ic->next)->key == op->key
7031         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7032         ) {
7033                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7034           return ic->next;
7035     }
7036
7037     /*
7038     if (ic->next &&
7039         ic->next->op == IFX &&
7040         IC_COND(ic->next)->key == op->key) {
7041       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7042       return ic->next;
7043     }
7044     */
7045
7046     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7047     if (ic->next &&
7048         ic->next->op == IFX)
7049       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7050
7051     if (ic->next &&
7052         ic->next->op == IFX &&
7053         IC_COND(ic->next)->key == op->key) {
7054       DEBUGpic16_emitcode ("; "," key is okay");
7055       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7056                            OP_SYMBOL(op)->liveTo,
7057                            ic->next->seq);
7058     }
7059
7060 #if 0
7061     /* the code below is completely untested
7062      * it just allows ulong2fs.c compile -- VR */
7063          
7064     ic = ic->next;
7065     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7066                                         __FILE__, __FUNCTION__, __LINE__);
7067         
7068     /* if this has register type condition and
7069     the next instruction is ifx with the same operand
7070     and live to of the operand is upto the ifx only then */
7071     if (ic->next &&
7072         ic->next->op == IFX &&
7073         IC_COND(ic->next)->key == op->key &&
7074         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7075         return ic->next;
7076
7077     if (ic->next &&
7078         ic->next->op == IFX &&
7079         IC_COND(ic->next)->key == op->key) {
7080       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7081       return ic->next;
7082     }
7083
7084     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7085                                         __FILE__, __FUNCTION__, __LINE__);
7086
7087 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7088 #endif
7089
7090     return NULL;
7091 }
7092 /*-----------------------------------------------------------------*/
7093 /* genAndOp - for && operation                                     */
7094 /*-----------------------------------------------------------------*/
7095 static void genAndOp (iCode *ic)
7096 {
7097   operand *left,*right, *result;
7098 /*     symbol *tlbl; */
7099
7100     FENTRY;
7101
7102     /* note here that && operations that are in an
7103     if statement are taken away by backPatchLabels
7104     only those used in arthmetic operations remain */
7105     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7106     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7107     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7108
7109     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7110
7111     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7112     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7113     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7114
7115     /* if both are bit variables */
7116 /*     if (AOP_TYPE(left) == AOP_CRY && */
7117 /*         AOP_TYPE(right) == AOP_CRY ) { */
7118 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7119 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7120 /*         pic16_outBitC(result); */
7121 /*     } else { */
7122 /*         tlbl = newiTempLabel(NULL); */
7123 /*         pic16_toBoolean(left);     */
7124 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7125 /*         pic16_toBoolean(right); */
7126 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7127 /*         pic16_outBitAcc(result); */
7128 /*     } */
7129
7130     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7131     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7132     pic16_freeAsmop(result,NULL,ic,TRUE);
7133 }
7134
7135
7136 /*-----------------------------------------------------------------*/
7137 /* genOrOp - for || operation                                      */
7138 /*-----------------------------------------------------------------*/
7139 /*
7140   tsd pic port -
7141   modified this code, but it doesn't appear to ever get called
7142 */
7143
7144 static void genOrOp (iCode *ic)
7145 {
7146   operand *left,*right, *result;
7147   symbol *tlbl;
7148
7149     FENTRY;  
7150
7151   /* note here that || operations that are in an
7152     if statement are taken away by backPatchLabels
7153     only those used in arthmetic operations remain */
7154     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7155     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7156     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7157
7158     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7159
7160     /* if both are bit variables */
7161     if (AOP_TYPE(left) == AOP_CRY &&
7162         AOP_TYPE(right) == AOP_CRY ) {
7163       pic16_emitcode("clrc","");
7164       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7165                AOP(left)->aopu.aop_dir,
7166                AOP(left)->aopu.aop_dir);
7167       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7168                AOP(right)->aopu.aop_dir,
7169                AOP(right)->aopu.aop_dir);
7170       pic16_emitcode("setc","");
7171
7172     } else {
7173         tlbl = newiTempLabel(NULL);
7174         pic16_toBoolean(left);
7175         emitSKPZ;
7176         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7177         pic16_toBoolean(right);
7178         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7179
7180         pic16_outBitAcc(result);
7181     }
7182
7183     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7184     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7185     pic16_freeAsmop(result,NULL,ic,TRUE);            
7186 }
7187
7188 /*-----------------------------------------------------------------*/
7189 /* isLiteralBit - test if lit == 2^n                               */
7190 /*-----------------------------------------------------------------*/
7191 static int isLiteralBit(unsigned long lit)
7192 {
7193     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7194     0x100L,0x200L,0x400L,0x800L,
7195     0x1000L,0x2000L,0x4000L,0x8000L,
7196     0x10000L,0x20000L,0x40000L,0x80000L,
7197     0x100000L,0x200000L,0x400000L,0x800000L,
7198     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7199     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7200     int idx;
7201     
7202     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7203     for(idx = 0; idx < 32; idx++)
7204         if(lit == pw[idx])
7205             return idx+1;
7206     return 0;
7207 }
7208
7209 /*-----------------------------------------------------------------*/
7210 /* continueIfTrue -                                                */
7211 /*-----------------------------------------------------------------*/
7212 static void continueIfTrue (iCode *ic)
7213 {
7214   FENTRY;
7215   if(IC_TRUE(ic))
7216     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7217   ic->generated = 1;
7218 }
7219
7220 /*-----------------------------------------------------------------*/
7221 /* jmpIfTrue -                                                     */
7222 /*-----------------------------------------------------------------*/
7223 static void jumpIfTrue (iCode *ic)
7224 {
7225   FENTRY;
7226   if(!IC_TRUE(ic))
7227     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7228   ic->generated = 1;
7229 }
7230
7231 /*-----------------------------------------------------------------*/
7232 /* jmpTrueOrFalse -                                                */
7233 /*-----------------------------------------------------------------*/
7234 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7235 {
7236   // ugly but optimized by peephole
7237   FENTRY;
7238   if(IC_TRUE(ic)){
7239     symbol *nlbl = newiTempLabel(NULL);
7240       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7241       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7242       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7243       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7244   } else {
7245     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7246     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7247   }
7248   ic->generated = 1;
7249 }
7250
7251 /*-----------------------------------------------------------------*/
7252 /* genAnd  - code for and                                          */
7253 /*-----------------------------------------------------------------*/
7254 static void genAnd (iCode *ic, iCode *ifx)
7255 {
7256   operand *left, *right, *result;
7257   int size, offset=0;  
7258   unsigned long lit = 0L;
7259   int bytelit = 0;
7260   resolvedIfx rIfx;
7261
7262     FENTRY;
7263     
7264   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7265   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7266   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7267
7268   resolveIfx(&rIfx,ifx);
7269
7270   /* if left is a literal & right is not then exchange them */
7271   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7272       AOP_NEEDSACC(left)) {
7273     operand *tmp = right ;
7274     right = left;
7275     left = tmp;
7276   }
7277
7278   /* if result = right then exchange them */
7279   if(pic16_sameRegs(AOP(result),AOP(right))){
7280     operand *tmp = right ;
7281     right = left;
7282     left = tmp;
7283   }
7284
7285   /* if right is bit then exchange them */
7286   if (AOP_TYPE(right) == AOP_CRY &&
7287       AOP_TYPE(left) != AOP_CRY){
7288     operand *tmp = right ;
7289     right = left;
7290     left = tmp;
7291   }
7292   if(AOP_TYPE(right) == AOP_LIT)
7293     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7294
7295   size = AOP_SIZE(result);
7296
7297   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7298
7299   // if(bit & yy)
7300   // result = bit & yy;
7301   if (AOP_TYPE(left) == AOP_CRY){
7302     // c = bit & literal;
7303     if(AOP_TYPE(right) == AOP_LIT){
7304       if(lit & 1) {
7305         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7306           // no change
7307           goto release;
7308         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7309       } else {
7310         // bit(result) = 0;
7311         if(size && (AOP_TYPE(result) == AOP_CRY)){
7312           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7313           goto release;
7314         }
7315         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7316           jumpIfTrue(ifx);
7317           goto release;
7318         }
7319         pic16_emitcode("clr","c");
7320       }
7321     } else {
7322       if (AOP_TYPE(right) == AOP_CRY){
7323         // c = bit & bit;
7324         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7325         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7326       } else {
7327         // c = bit & val;
7328         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7329         // c = lsb
7330         pic16_emitcode("rrc","a");
7331         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7332       }
7333     }
7334     // bit = c
7335     // val = c
7336     if(size)
7337       pic16_outBitC(result);
7338     // if(bit & ...)
7339     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7340       genIfxJump(ifx, "c");           
7341     goto release ;
7342   }
7343
7344   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7345   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7346   if((AOP_TYPE(right) == AOP_LIT) &&
7347      (AOP_TYPE(result) == AOP_CRY) &&
7348      (AOP_TYPE(left) != AOP_CRY)){
7349     int posbit = isLiteralBit(lit);
7350     /* left &  2^n */
7351     if(posbit){
7352       posbit--;
7353       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7354       // bit = left & 2^n
7355       if(size)
7356         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7357       // if(left &  2^n)
7358       else{
7359         if(ifx){
7360 /*
7361           if(IC_TRUE(ifx)) {
7362             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7363             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7364           } else {
7365             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7366             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7367           }
7368 */
7369         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7370         size = AOP_SIZE(left);
7371
7372         {
7373           int bp = posbit, ofs=0;
7374           
7375             while(bp > 7) {
7376               bp -= 8;
7377               ofs++;
7378             }
7379
7380           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7381                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7382
7383         }
7384 /*
7385           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7386                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7387 */
7388           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7389           
7390           ifx->generated = 1;
7391         }
7392         goto release;
7393       }
7394     } else {
7395       symbol *tlbl = newiTempLabel(NULL);
7396       int sizel = AOP_SIZE(left);
7397
7398       if(size)
7399         emitSETC;
7400
7401       while(sizel--) {
7402         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7403
7404           /* patch provided by Aaron Colwell */
7405           if((posbit = isLiteralBit(bytelit)) != 0) {
7406               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7407                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7408                                                 (posbit-1),0, PO_GPR_REGISTER));
7409
7410               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7411 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7412           } else {
7413               if (bytelit == 0xff) {
7414                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7415                    * a peephole could optimize it out -- VR */
7416                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7417               } else {
7418                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7419                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7420               }
7421
7422               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7423                             pic16_popGetLabel(tlbl->key));
7424           }
7425         
7426 #if 0
7427           /* old code, left here for reference -- VR 09/2004 */
7428           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7429           // byte ==  2^n ?
7430           if((posbit = isLiteralBit(bytelit)) != 0)
7431             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7432           else{
7433             if(bytelit != 0x0FFL)
7434               pic16_emitcode("anl","a,%s",
7435                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7436             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7437           }
7438 #endif
7439         }
7440         offset++;
7441       }
7442       // bit = left & literal
7443       if(size) {
7444         emitCLRC;
7445         pic16_emitpLabel(tlbl->key);
7446       }
7447       // if(left & literal)
7448       else {
7449         if(ifx) {
7450           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7451           ifx->generated = 1;
7452         }
7453         pic16_emitpLabel(tlbl->key);
7454         goto release;
7455       }
7456     }
7457
7458     pic16_outBitC(result);
7459     goto release ;
7460   }
7461
7462   /* if left is same as result */
7463   if(pic16_sameRegs(AOP(result),AOP(left))){
7464     int know_W = -1;
7465     for(;size--; offset++,lit>>=8) {
7466       if(AOP_TYPE(right) == AOP_LIT){
7467         switch(lit & 0xff) {
7468         case 0x00:
7469           /*  and'ing with 0 has clears the result */
7470 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7471           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7472           break;
7473         case 0xff:
7474           /* and'ing with 0xff is a nop when the result and left are the same */
7475           break;
7476
7477         default:
7478           {
7479             int p = pic16_my_powof2( (~lit) & 0xff );
7480             if(p>=0) {
7481               /* only one bit is set in the literal, so use a bcf instruction */
7482 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7483               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7484
7485             } else {
7486               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7487               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7488               if(know_W != (lit&0xff))
7489                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7490               know_W = lit &0xff;
7491               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7492             }
7493           }    
7494         }
7495       } else {
7496         if (AOP_TYPE(left) == AOP_ACC) {
7497           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7498         } else {                    
7499           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7500           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7501
7502         }
7503       }
7504     }
7505
7506   } else {
7507     // left & result in different registers
7508     if(AOP_TYPE(result) == AOP_CRY){
7509       // result = bit
7510       // if(size), result in bit
7511       // if(!size && ifx), conditional oper: if(left & right)
7512       symbol *tlbl = newiTempLabel(NULL);
7513       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7514       if(size)
7515         pic16_emitcode("setb","c");
7516       while(sizer--){
7517         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7518         pic16_emitcode("anl","a,%s",
7519                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7520         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7521         offset++;
7522       }
7523       if(size){
7524         CLRC;
7525         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7526         pic16_outBitC(result);
7527       } else if(ifx)
7528         jmpTrueOrFalse(ifx, tlbl);
7529     } else {
7530       for(;(size--);offset++) {
7531         // normal case
7532         // result = left & right
7533         if(AOP_TYPE(right) == AOP_LIT){
7534           int t = (lit >> (offset*8)) & 0x0FFL;
7535           switch(t) { 
7536           case 0x00:
7537             pic16_emitcode("clrf","%s",
7538                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7539             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7540             break;
7541           case 0xff:
7542             pic16_emitcode("movf","%s,w",
7543                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7544             pic16_emitcode("movwf","%s",
7545                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7546             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7547             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7548             break;
7549           default:
7550             pic16_emitcode("movlw","0x%x",t);
7551             pic16_emitcode("andwf","%s,w",
7552                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7553             pic16_emitcode("movwf","%s",
7554                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7555               
7556             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7557             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7558             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7559           }
7560           continue;
7561         }
7562
7563         if (AOP_TYPE(left) == AOP_ACC) {
7564           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7565           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7566         } else {
7567           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7568           pic16_emitcode("andwf","%s,w",
7569                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7570           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7571           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7572         }
7573         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7574         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7575       }
7576     }
7577   }
7578
7579   release :
7580     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7581   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7582   pic16_freeAsmop(result,NULL,ic,TRUE);     
7583 }
7584
7585 /*-----------------------------------------------------------------*/
7586 /* genOr  - code for or                                            */
7587 /*-----------------------------------------------------------------*/
7588 static void genOr (iCode *ic, iCode *ifx)
7589 {
7590     operand *left, *right, *result;
7591     int size, offset=0;
7592     unsigned long lit = 0L;
7593
7594     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7595
7596     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7597     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7598     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7599
7600     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7601
7602     /* if left is a literal & right is not then exchange them */
7603     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7604         AOP_NEEDSACC(left)) {
7605         operand *tmp = right ;
7606         right = left;
7607         left = tmp;
7608     }
7609
7610     /* if result = right then exchange them */
7611     if(pic16_sameRegs(AOP(result),AOP(right))){
7612         operand *tmp = right ;
7613         right = left;
7614         left = tmp;
7615     }
7616
7617     /* if right is bit then exchange them */
7618     if (AOP_TYPE(right) == AOP_CRY &&
7619         AOP_TYPE(left) != AOP_CRY){
7620         operand *tmp = right ;
7621         right = left;
7622         left = tmp;
7623     }
7624
7625     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7626
7627     if(AOP_TYPE(right) == AOP_LIT)
7628         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7629
7630     size = AOP_SIZE(result);
7631
7632     // if(bit | yy)
7633     // xx = bit | yy;
7634     if (AOP_TYPE(left) == AOP_CRY){
7635         if(AOP_TYPE(right) == AOP_LIT){
7636             // c = bit & literal;
7637             if(lit){
7638                 // lit != 0 => result = 1
7639                 if(AOP_TYPE(result) == AOP_CRY){
7640                   if(size)
7641                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7642                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7643                   //     AOP(result)->aopu.aop_dir,
7644                   //     AOP(result)->aopu.aop_dir);
7645                     else if(ifx)
7646                         continueIfTrue(ifx);
7647                     goto release;
7648                 }
7649             } else {
7650                 // lit == 0 => result = left
7651                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7652                     goto release;
7653                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7654             }
7655         } else {
7656             if (AOP_TYPE(right) == AOP_CRY){
7657               if(pic16_sameRegs(AOP(result),AOP(left))){
7658                 // c = bit | bit;
7659                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7660                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7661                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7662
7663                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7664                          AOP(result)->aopu.aop_dir,
7665                          AOP(result)->aopu.aop_dir);
7666                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7667                          AOP(right)->aopu.aop_dir,
7668                          AOP(right)->aopu.aop_dir);
7669                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7670                          AOP(result)->aopu.aop_dir,
7671                          AOP(result)->aopu.aop_dir);
7672               } else {
7673                 if( AOP_TYPE(result) == AOP_ACC) {
7674                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7675                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7676                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7677                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7678
7679                 } else {
7680
7681                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7682                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7683                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7684                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7685
7686                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7687                                  AOP(result)->aopu.aop_dir,
7688                                  AOP(result)->aopu.aop_dir);
7689                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7690                                  AOP(right)->aopu.aop_dir,
7691                                  AOP(right)->aopu.aop_dir);
7692                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7693                                  AOP(left)->aopu.aop_dir,
7694                                  AOP(left)->aopu.aop_dir);
7695                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7696                                  AOP(result)->aopu.aop_dir,
7697                                  AOP(result)->aopu.aop_dir);
7698                 }
7699               }
7700             } else {
7701                 // c = bit | val;
7702                 symbol *tlbl = newiTempLabel(NULL);
7703                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7704
7705
7706                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7707                 if( AOP_TYPE(right) == AOP_ACC) {
7708                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7709                   emitSKPNZ;
7710                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7711                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7712                 }
7713
7714
7715
7716                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7717                     pic16_emitcode(";XXX setb","c");
7718                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7719                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7720                 pic16_toBoolean(right);
7721                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7722                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7723                     jmpTrueOrFalse(ifx, tlbl);
7724                     goto release;
7725                 } else {
7726                     CLRC;
7727                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7728                 }
7729             }
7730         }
7731         // bit = c
7732         // val = c
7733         if(size)
7734             pic16_outBitC(result);
7735         // if(bit | ...)
7736         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7737             genIfxJump(ifx, "c");           
7738         goto release ;
7739     }
7740
7741     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7742     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7743     if((AOP_TYPE(right) == AOP_LIT) &&
7744        (AOP_TYPE(result) == AOP_CRY) &&
7745        (AOP_TYPE(left) != AOP_CRY)){
7746         if(lit){
7747           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7748             // result = 1
7749             if(size)
7750                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7751             else 
7752                 continueIfTrue(ifx);
7753             goto release;
7754         } else {
7755           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7756             // lit = 0, result = boolean(left)
7757             if(size)
7758                 pic16_emitcode(";XXX setb","c");
7759             pic16_toBoolean(right);
7760             if(size){
7761                 symbol *tlbl = newiTempLabel(NULL);
7762                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7763                 CLRC;
7764                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7765             } else {
7766                 genIfxJump (ifx,"a");
7767                 goto release;
7768             }
7769         }
7770         pic16_outBitC(result);
7771         goto release ;
7772     }
7773
7774     /* if left is same as result */
7775     if(pic16_sameRegs(AOP(result),AOP(left))){
7776       int know_W = -1;
7777       for(;size--; offset++,lit>>=8) {
7778         if(AOP_TYPE(right) == AOP_LIT){
7779           if((lit & 0xff) == 0)
7780             /*  or'ing with 0 has no effect */
7781             continue;
7782           else {
7783             int p = pic16_my_powof2(lit & 0xff);
7784             if(p>=0) {
7785               /* only one bit is set in the literal, so use a bsf instruction */
7786               pic16_emitpcode(POC_BSF,
7787                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7788             } else {
7789               if(know_W != (lit & 0xff))
7790                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7791               know_W = lit & 0xff;
7792               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7793             }
7794                     
7795           }
7796         } else {
7797           if (AOP_TYPE(left) == AOP_ACC) {
7798             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7799             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7800           } else {                  
7801             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7802             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7803
7804             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7805             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7806
7807           }
7808         }
7809       }
7810     } else {
7811         // left & result in different registers
7812         if(AOP_TYPE(result) == AOP_CRY){
7813             // result = bit
7814             // if(size), result in bit
7815             // if(!size && ifx), conditional oper: if(left | right)
7816             symbol *tlbl = newiTempLabel(NULL);
7817             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7818             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7819
7820
7821             if(size)
7822                 pic16_emitcode(";XXX setb","c");
7823             while(sizer--){
7824                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7825                 pic16_emitcode(";XXX orl","a,%s",
7826                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7827                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7828                 offset++;
7829             }
7830             if(size){
7831                 CLRC;
7832                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7833                 pic16_outBitC(result);
7834             } else if(ifx)
7835                 jmpTrueOrFalse(ifx, tlbl);
7836         } else for(;(size--);offset++){
7837           // normal case
7838           // result = left & right
7839           if(AOP_TYPE(right) == AOP_LIT){
7840             int t = (lit >> (offset*8)) & 0x0FFL;
7841             switch(t) { 
7842             case 0x00:
7843               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7844               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7845
7846               pic16_emitcode("movf","%s,w",
7847                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7848               pic16_emitcode("movwf","%s",
7849                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7850               break;
7851             default:
7852               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7853               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7854               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7855
7856               pic16_emitcode("movlw","0x%x",t);
7857               pic16_emitcode("iorwf","%s,w",
7858                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7859               pic16_emitcode("movwf","%s",
7860                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7861               
7862             }
7863             continue;
7864           }
7865
7866           // faster than result <- left, anl result,right
7867           // and better if result is SFR
7868           if (AOP_TYPE(left) == AOP_ACC) {
7869             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7870             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7871           } else {
7872             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7873             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7874
7875             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7876             pic16_emitcode("iorwf","%s,w",
7877                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7878           }
7879           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7880           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7881         }
7882     }
7883
7884 release :
7885     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7886     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7887     pic16_freeAsmop(result,NULL,ic,TRUE);     
7888 }
7889
7890 /*-----------------------------------------------------------------*/
7891 /* genXor - code for xclusive or                                   */
7892 /*-----------------------------------------------------------------*/
7893 static void genXor (iCode *ic, iCode *ifx)
7894 {
7895   operand *left, *right, *result;
7896   int size, offset=0;
7897   unsigned long lit = 0L;
7898
7899   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7900
7901   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7902   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7903   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7904
7905   /* if left is a literal & right is not ||
7906      if left needs acc & right does not */
7907   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7908       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7909     operand *tmp = right ;
7910     right = left;
7911     left = tmp;
7912   }
7913
7914   /* if result = right then exchange them */
7915   if(pic16_sameRegs(AOP(result),AOP(right))){
7916     operand *tmp = right ;
7917     right = left;
7918     left = tmp;
7919   }
7920
7921   /* if right is bit then exchange them */
7922   if (AOP_TYPE(right) == AOP_CRY &&
7923       AOP_TYPE(left) != AOP_CRY){
7924     operand *tmp = right ;
7925     right = left;
7926     left = tmp;
7927   }
7928   if(AOP_TYPE(right) == AOP_LIT)
7929     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7930
7931   size = AOP_SIZE(result);
7932
7933   // if(bit ^ yy)
7934   // xx = bit ^ yy;
7935   if (AOP_TYPE(left) == AOP_CRY){
7936     if(AOP_TYPE(right) == AOP_LIT){
7937       // c = bit & literal;
7938       if(lit>>1){
7939         // lit>>1  != 0 => result = 1
7940         if(AOP_TYPE(result) == AOP_CRY){
7941           if(size)
7942             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
7943             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7944           else if(ifx)
7945             continueIfTrue(ifx);
7946           goto release;
7947         }
7948         pic16_emitcode("setb","c");
7949       } else{
7950         // lit == (0 or 1)
7951         if(lit == 0){
7952           // lit == 0, result = left
7953           if(size && pic16_sameRegs(AOP(result),AOP(left)))
7954             goto release;
7955           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7956         } else{
7957           // lit == 1, result = not(left)
7958           if(size && pic16_sameRegs(AOP(result),AOP(left))){
7959             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
7960             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
7961             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7962             goto release;
7963           } else {
7964             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7965             pic16_emitcode("cpl","c");
7966           }
7967         }
7968       }
7969
7970     } else {
7971       // right != literal
7972       symbol *tlbl = newiTempLabel(NULL);
7973       if (AOP_TYPE(right) == AOP_CRY){
7974         // c = bit ^ bit;
7975         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7976       }
7977       else{
7978         int sizer = AOP_SIZE(right);
7979         // c = bit ^ val
7980         // if val>>1 != 0, result = 1
7981         pic16_emitcode("setb","c");
7982         while(sizer){
7983           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
7984           if(sizer == 1)
7985             // test the msb of the lsb
7986             pic16_emitcode("anl","a,#0xfe");
7987           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7988           sizer--;
7989         }
7990         // val = (0,1)
7991         pic16_emitcode("rrc","a");
7992       }
7993       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
7994       pic16_emitcode("cpl","c");
7995       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
7996     }
7997     // bit = c
7998     // val = c
7999     if(size)
8000       pic16_outBitC(result);
8001     // if(bit | ...)
8002     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8003       genIfxJump(ifx, "c");           
8004     goto release ;
8005   }
8006
8007   if(pic16_sameRegs(AOP(result),AOP(left))){
8008     /* if left is same as result */
8009     for(;size--; offset++) {
8010       if(AOP_TYPE(right) == AOP_LIT){
8011         int t  = (lit >> (offset*8)) & 0x0FFL;
8012         if(t == 0x00L)
8013           continue;
8014         else
8015           if (IS_AOP_PREG(left)) {
8016             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8017             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8018             pic16_aopPut(AOP(result),"a",offset);
8019           } else {
8020             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8021             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8022             pic16_emitcode("xrl","%s,%s",
8023                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8024                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8025           }
8026       } else {
8027         if (AOP_TYPE(left) == AOP_ACC)
8028           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8029         else {
8030           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8031           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8032 /*
8033           if (IS_AOP_PREG(left)) {
8034             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8035             pic16_aopPut(AOP(result),"a",offset);
8036           } else
8037             pic16_emitcode("xrl","%s,a",
8038                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8039 */
8040         }
8041       }
8042     }
8043   } else {
8044     // left & result in different registers
8045     if(AOP_TYPE(result) == AOP_CRY){
8046       // result = bit
8047       // if(size), result in bit
8048       // if(!size && ifx), conditional oper: if(left ^ right)
8049       symbol *tlbl = newiTempLabel(NULL);
8050       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8051       if(size)
8052         pic16_emitcode("setb","c");
8053       while(sizer--){
8054         if((AOP_TYPE(right) == AOP_LIT) &&
8055            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8056           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8057         } else {
8058           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8059           pic16_emitcode("xrl","a,%s",
8060                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8061         }
8062         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8063         offset++;
8064       }
8065       if(size){
8066         CLRC;
8067         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8068         pic16_outBitC(result);
8069       } else if(ifx)
8070         jmpTrueOrFalse(ifx, tlbl);
8071     } else for(;(size--);offset++){
8072       // normal case
8073       // result = left & right
8074       if(AOP_TYPE(right) == AOP_LIT){
8075         int t = (lit >> (offset*8)) & 0x0FFL;
8076         switch(t) { 
8077         case 0x00:
8078           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8079           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8080           pic16_emitcode("movf","%s,w",
8081                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8082           pic16_emitcode("movwf","%s",
8083                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8084           break;
8085         case 0xff:
8086           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8087           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8088           pic16_emitcode("comf","%s,w",
8089                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8090           pic16_emitcode("movwf","%s",
8091                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8092           break;
8093         default:
8094           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8095           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8096           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8097           pic16_emitcode("movlw","0x%x",t);
8098           pic16_emitcode("xorwf","%s,w",
8099                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8100           pic16_emitcode("movwf","%s",
8101                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8102
8103         }
8104         continue;
8105       }
8106
8107       // faster than result <- left, anl result,right
8108       // and better if result is SFR
8109       if (AOP_TYPE(left) == AOP_ACC) {
8110         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8111         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8112       } else {
8113         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8114         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8115         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8116         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8117       }
8118       if ( AOP_TYPE(result) != AOP_ACC){
8119         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8120         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8121       }
8122     }
8123   }
8124
8125   release :
8126     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8127   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8128   pic16_freeAsmop(result,NULL,ic,TRUE);     
8129 }
8130
8131 /*-----------------------------------------------------------------*/
8132 /* genInline - write the inline code out                           */
8133 /*-----------------------------------------------------------------*/
8134 static void genInline (iCode *ic)
8135 {
8136   char *buffer, *bp, *bp1;
8137     
8138         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8139
8140         _G.inLine += (!options.asmpeep);
8141
8142         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8143         strcpy(buffer,IC_INLINE(ic));
8144         
8145         while((bp1=strstr(bp, "\\n"))) {
8146           *bp1++ = '\n';
8147           *bp1++ = ' ';
8148           bp = bp1;
8149         }
8150         bp = bp1 = buffer;
8151
8152 #if 0
8153   /* This is an experimental code for #pragma inline
8154      and is temporarily disabled for 2.5.0 release */
8155         if(asmInlineMap)
8156         {
8157           symbol *sym;
8158           char *s;
8159           char *cbuf;
8160           int cblen;
8161
8162             cbuf = Safe_strdup(buffer);
8163             cblen = strlen(buffer)+1;
8164             memset(cbuf, 0, cblen);
8165
8166             bp = buffer;
8167             bp1 = cbuf;
8168             while(*bp) {
8169               if(*bp != '%')*bp1++ = *bp++;
8170               else {
8171                 int i;
8172
8173                   bp++;
8174                   i = *bp - '0';
8175                   if(i>elementsInSet(asmInlineMap))break;
8176                   
8177                   bp++;
8178                   s = indexSet(asmInlineMap, i);
8179                   DEBUGpc("searching symbol s = `%s'", s);
8180                   sym = findSym(SymbolTab, NULL, s);
8181
8182                   if(sym->reqv) {
8183                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8184                   } else {
8185                     strcat(bp1, sym->rname);
8186                   }
8187                   
8188                   while(*bp1)bp1++;
8189               }
8190               
8191               if(strlen(bp1) > cblen - 16) {
8192                 int i = strlen(cbuf);
8193                 cblen += 50;
8194                 cbuf = realloc(cbuf, cblen);
8195                 memset(cbuf+i, 0, 50);
8196                 bp1 = cbuf + i;
8197               }
8198             }
8199             
8200             free(buffer);
8201             buffer = Safe_strdup( cbuf );
8202             free(cbuf);
8203             
8204             bp = bp1 = buffer;
8205         }
8206 #endif  /* 0 */
8207
8208         /* emit each line as a code */
8209         while (*bp) {
8210                 if (*bp == '\n') {
8211                         *bp++ = '\0';
8212
8213                         if(*bp1)
8214                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8215                         bp1 = bp;
8216                 } else {
8217                         if (*bp == ':') {
8218                                 bp++;
8219                                 *bp = '\0';
8220                                 bp++;
8221
8222                                 /* print label, use this special format with NULL directive
8223                                  * to denote that the argument should not be indented with tab */
8224                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8225                                 bp1 = bp;
8226                         } else
8227                                 bp++;
8228                 }
8229         }
8230
8231         if ((bp1 != bp) && *bp1)
8232                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8233
8234
8235     Safe_free(buffer);
8236
8237     _G.inLine -= (!options.asmpeep);
8238 }
8239
8240 /*-----------------------------------------------------------------*/
8241 /* genRRC - rotate right with carry                                */
8242 /*-----------------------------------------------------------------*/
8243 static void genRRC (iCode *ic)
8244 {
8245   operand *left , *result ;
8246   int size, offset = 0, same;
8247
8248   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8249
8250   /* rotate right with carry */
8251   left = IC_LEFT(ic);
8252   result=IC_RESULT(ic);
8253   pic16_aopOp (left,ic,FALSE);
8254   pic16_aopOp (result,ic,TRUE);
8255
8256   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8257
8258   same = pic16_sameRegs(AOP(result),AOP(left));
8259
8260   size = AOP_SIZE(result);    
8261
8262   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8263
8264   /* get the lsb and put it into the carry */
8265   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8266
8267   offset = 0 ;
8268
8269   while(size--) {
8270
8271     if(same) {
8272       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8273     } else {
8274       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8275       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8276     }
8277
8278     offset++;
8279   }
8280
8281   pic16_freeAsmop(left,NULL,ic,TRUE);
8282   pic16_freeAsmop(result,NULL,ic,TRUE);
8283 }
8284
8285 /*-----------------------------------------------------------------*/
8286 /* genRLC - generate code for rotate left with carry               */
8287 /*-----------------------------------------------------------------*/
8288 static void genRLC (iCode *ic)
8289 {    
8290   operand *left , *result ;
8291   int size, offset = 0;
8292   int same;
8293
8294   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8295   /* rotate right with carry */
8296   left = IC_LEFT(ic);
8297   result=IC_RESULT(ic);
8298   pic16_aopOp (left,ic,FALSE);
8299   pic16_aopOp (result,ic,TRUE);
8300
8301   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8302
8303   same = pic16_sameRegs(AOP(result),AOP(left));
8304
8305   /* move it to the result */
8306   size = AOP_SIZE(result);    
8307
8308   /* get the msb and put it into the carry */
8309   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8310
8311   offset = 0 ;
8312
8313   while(size--) {
8314
8315     if(same) {
8316       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8317     } else {
8318       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8319       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8320     }
8321
8322     offset++;
8323   }
8324
8325
8326   pic16_freeAsmop(left,NULL,ic,TRUE);
8327   pic16_freeAsmop(result,NULL,ic,TRUE);
8328 }
8329
8330
8331 /* gpasm can get the highest order bit with HIGH/UPPER
8332  * so the following probably is not needed -- VR */
8333  
8334 /*-----------------------------------------------------------------*/
8335 /* genGetHbit - generates code get highest order bit               */
8336 /*-----------------------------------------------------------------*/
8337 static void genGetHbit (iCode *ic)
8338 {
8339     operand *left, *result;
8340     left = IC_LEFT(ic);
8341     result=IC_RESULT(ic);
8342     pic16_aopOp (left,ic,FALSE);
8343     pic16_aopOp (result,ic,FALSE);
8344
8345     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8346     /* get the highest order byte into a */
8347     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8348     if(AOP_TYPE(result) == AOP_CRY){
8349         pic16_emitcode("rlc","a");
8350         pic16_outBitC(result);
8351     }
8352     else{
8353         pic16_emitcode("rl","a");
8354         pic16_emitcode("anl","a,#0x01");
8355         pic16_outAcc(result);
8356     }
8357
8358
8359     pic16_freeAsmop(left,NULL,ic,TRUE);
8360     pic16_freeAsmop(result,NULL,ic,TRUE);
8361 }
8362
8363 #if 0
8364 /*-----------------------------------------------------------------*/
8365 /* AccRol - rotate left accumulator by known count                 */
8366 /*-----------------------------------------------------------------*/
8367 static void AccRol (int shCount)
8368 {
8369     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8370     shCount &= 0x0007;              // shCount : 0..7
8371     switch(shCount){
8372         case 0 :
8373             break;
8374         case 1 :
8375             pic16_emitcode("rl","a");
8376             break;
8377         case 2 :
8378             pic16_emitcode("rl","a");
8379             pic16_emitcode("rl","a");
8380             break;
8381         case 3 :
8382             pic16_emitcode("swap","a");
8383             pic16_emitcode("rr","a");
8384             break;
8385         case 4 :
8386             pic16_emitcode("swap","a");
8387             break;
8388         case 5 :
8389             pic16_emitcode("swap","a");
8390             pic16_emitcode("rl","a");
8391             break;
8392         case 6 :
8393             pic16_emitcode("rr","a");
8394             pic16_emitcode("rr","a");
8395             break;
8396         case 7 :
8397             pic16_emitcode("rr","a");
8398             break;
8399     }
8400 }
8401 #endif
8402
8403 /*-----------------------------------------------------------------*/
8404 /* AccLsh - left shift accumulator by known count                  */
8405 /*-----------------------------------------------------------------*/
8406 static void AccLsh (int shCount)
8407 {
8408         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8409         switch(shCount){
8410                 case 0 :
8411                         return;
8412                         break;
8413                 case 1 :
8414                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8415                         break;
8416                 case 2 :
8417                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8418                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8419                         break;
8420                 case 3 :
8421                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8422                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8423                         break;
8424                 case 4 :
8425                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8426                         break;
8427                 case 5 :
8428                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8429                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8430                         break;
8431                 case 6 :
8432                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8433                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8434                         break;
8435                 case 7 :
8436                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8437                         break;
8438         }
8439
8440         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8441 }
8442
8443 /*-----------------------------------------------------------------*/
8444 /* AccRsh - right shift accumulator by known count                 */
8445 /*-----------------------------------------------------------------*/
8446 static void AccRsh (int shCount, int andmask)
8447 {
8448         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8449         switch(shCount){
8450                 case 0 :
8451                         return; break;
8452                 case 1 :
8453                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8454                         break;
8455                 case 2 :
8456                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8457                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8458                         break;
8459                 case 3 :
8460                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8461                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8462                         break;
8463                 case 4 :
8464                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8465                         break;
8466                 case 5 :
8467                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8468                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8469                         break;
8470                 case 6 :
8471                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8472                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8473                         break;
8474                 case 7 :
8475                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8476                         break;
8477         }
8478         
8479         if(andmask)
8480                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8481         else
8482                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8483 }
8484
8485 #if 0
8486 /*-----------------------------------------------------------------*/
8487 /* AccSRsh - signed right shift accumulator by known count                 */
8488 /*-----------------------------------------------------------------*/
8489 static void AccSRsh (int shCount)
8490 {
8491     symbol *tlbl ;
8492     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8493     if(shCount != 0){
8494         if(shCount == 1){
8495             pic16_emitcode("mov","c,acc.7");
8496             pic16_emitcode("rrc","a");
8497         } else if(shCount == 2){
8498             pic16_emitcode("mov","c,acc.7");
8499             pic16_emitcode("rrc","a");
8500             pic16_emitcode("mov","c,acc.7");
8501             pic16_emitcode("rrc","a");
8502         } else {
8503             tlbl = newiTempLabel(NULL);
8504             /* rotate right accumulator */
8505             AccRol(8 - shCount);
8506             /* and kill the higher order bits */
8507             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8508             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8509             pic16_emitcode("orl","a,#0x%02x",
8510                      (unsigned char)~SRMask[shCount]);
8511             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8512         }
8513     }
8514 }
8515 #endif
8516
8517 /*-----------------------------------------------------------------*/
8518 /* shiftR1Left2Result - shift right one byte from left to result   */
8519 /*-----------------------------------------------------------------*/
8520 static void shiftR1Left2ResultSigned (operand *left, int offl,
8521                                 operand *result, int offr,
8522                                 int shCount)
8523 {
8524   int same;
8525
8526   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8527
8528   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8529
8530   switch(shCount) {
8531   case 1:
8532     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8533     if(same) 
8534       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8535     else {
8536       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8537       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8538     }
8539
8540     break;
8541   case 2:
8542
8543     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8544     if(same) 
8545       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8546     else {
8547       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8548       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8549     }
8550     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8551     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8552
8553     break;
8554
8555   case 3:
8556     if(same)
8557       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8558     else {
8559       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8560       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8561     }
8562
8563     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8564     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8565     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8566
8567     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8568     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8569
8570     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8571     break;
8572
8573   case 4:
8574     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8575     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8576     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8577     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8578     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8579     break;
8580   case 5:
8581     if(same) {
8582       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8583     } else {
8584       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8585       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8586     }
8587     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8588     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8589     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8590     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8591     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8592     break;
8593
8594   case 6:
8595     if(same) {
8596       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8597       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8598       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8599       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8600       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8601       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8602     } else {
8603       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8604       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8605       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8606       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8607       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8608     }
8609     break;
8610
8611   case 7:
8612     if(same) {
8613       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8614       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8615       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8616       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8617     } else {
8618       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8619       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8620       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8621     }
8622
8623   default:
8624     break;
8625   }
8626 }
8627
8628 /*-----------------------------------------------------------------*/
8629 /* shiftR1Left2Result - shift right one byte from left to result   */
8630 /*-----------------------------------------------------------------*/
8631 static void shiftR1Left2Result (operand *left, int offl,
8632                                 operand *result, int offr,
8633                                 int shCount, int sign)
8634 {
8635   int same;
8636
8637   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8638
8639   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8640
8641   /* Copy the msb into the carry if signed. */
8642   if(sign) {
8643     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8644     return;
8645   }
8646
8647
8648
8649   switch(shCount) {
8650   case 1:
8651     emitCLRC;
8652     if(same) 
8653       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8654     else {
8655       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8656       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8657     }
8658     break;
8659   case 2:
8660     emitCLRC;
8661     if(same) {
8662       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8663     } else {
8664       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8665       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8666     }
8667     emitCLRC;
8668     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8669
8670     break;
8671   case 3:
8672     if(same)
8673       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8674     else {
8675       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8676       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8677     }
8678
8679     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8680     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8681     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8682     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8683     break;
8684       
8685   case 4:
8686     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8687     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8688     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8689     break;
8690
8691   case 5:
8692     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8693     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8694     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8695     //emitCLRC;
8696     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8697
8698     break;
8699   case 6:
8700
8701     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8702     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8703     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8704     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8705     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8706     break;
8707
8708   case 7:
8709
8710     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8711     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8712     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8713
8714     break;
8715
8716   default:
8717     break;
8718   }
8719 }
8720
8721 /*-----------------------------------------------------------------*/
8722 /* shiftL1Left2Result - shift left one byte from left to result    */
8723 /*-----------------------------------------------------------------*/
8724 static void shiftL1Left2Result (operand *left, int offl,
8725                                 operand *result, int offr, int shCount)
8726 {
8727   int same;
8728
8729   //    char *l;
8730   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8731
8732   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8733   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8734     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8735     //    MOVA(l);
8736     /* shift left accumulator */
8737     //AccLsh(shCount); // don't comment out just yet...
8738   //    pic16_aopPut(AOP(result),"a",offr);
8739
8740   switch(shCount) {
8741   case 1:
8742     /* Shift left 1 bit position */
8743     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8744     if(same) {
8745       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8746     } else {
8747       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8748       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8749     }
8750     break;
8751   case 2:
8752     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8753     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8754     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8755     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8756     break;
8757   case 3:
8758     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8759     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8760     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8761     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8762     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8763     break;
8764   case 4:
8765     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8766     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8767     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8768     break;
8769   case 5:
8770     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8771     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8772     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8773     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8774     break;
8775   case 6:
8776     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8777     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8778     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8779     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8780     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8781     break;
8782   case 7:
8783     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8784     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8785     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8786     break;
8787
8788   default:
8789     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8790   }
8791
8792 }
8793
8794 /*-----------------------------------------------------------------*/
8795 /* movLeft2Result - move byte from left to result                  */
8796 /*-----------------------------------------------------------------*/
8797 static void movLeft2Result (operand *left, int offl,
8798                             operand *result, int offr)
8799 {
8800   char *l;
8801   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8802   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8803     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8804
8805     if (*l == '@' && (IS_AOP_PREG(result))) {
8806       pic16_emitcode("mov","a,%s",l);
8807       pic16_aopPut(AOP(result),"a",offr);
8808     } else {
8809       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8810       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8811     }
8812   }
8813 }
8814
8815 /*-----------------------------------------------------------------*/
8816 /* shiftL2Left2Result - shift left two bytes from left to result   */
8817 /*-----------------------------------------------------------------*/
8818 static void shiftL2Left2Result (operand *left, int offl,
8819                                 operand *result, int offr, int shCount)
8820 {
8821   int same = pic16_sameRegs(AOP(result), AOP(left));
8822   int i;
8823
8824   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8825
8826   if (same && (offl != offr)) { // shift bytes
8827     if (offr > offl) {
8828        for(i=1;i>-1;i--) {
8829          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8830          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8831        }
8832     } else { // just treat as different later on
8833                 same = 0;
8834     }
8835   }
8836
8837   if(same) {
8838     switch(shCount) {
8839     case 0:
8840       break;
8841     case 1:
8842     case 2:
8843     case 3:
8844
8845       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8846       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8847       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8848
8849       while(--shCount) {
8850                 emitCLRC;
8851                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8852                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8853       }
8854
8855       break;
8856     case 4:
8857     case 5:
8858       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8859       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8860       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8861       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8862       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8863       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8864       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8865       if(shCount >=5) {
8866                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8867                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8868       }
8869       break;
8870     case 6:
8871       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8872       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8873       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8874       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8875       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8876       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8877       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8878       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8879       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8880       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8881       break;
8882     case 7:
8883       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8884       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8885       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8886       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8887       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8888     }
8889
8890   } else {
8891     switch(shCount) {
8892     case 0:
8893       break;
8894     case 1:
8895     case 2:
8896     case 3:
8897       /* note, use a mov/add for the shift since the mov has a
8898          chance of getting optimized out */
8899       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8900       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8901       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8902       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8903       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8904
8905       while(--shCount) {
8906                 emitCLRC;
8907                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8908                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8909       }
8910       break;
8911
8912     case 4:
8913     case 5:
8914       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8915       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8916       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8917       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8918       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8919       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8920       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8921       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8922
8923
8924       if(shCount == 5) {
8925                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8926                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8927       }
8928       break;
8929     case 6:
8930       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8931       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8932       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8933       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8934
8935       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8936       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8937       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8938       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8939       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8940       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8941       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8942       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8943       break;
8944     case 7:
8945       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8946       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8947       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8948       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8949       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8950     }
8951   }
8952
8953 }
8954 /*-----------------------------------------------------------------*/
8955 /* shiftR2Left2Result - shift right two bytes from left to result  */
8956 /*-----------------------------------------------------------------*/
8957 static void shiftR2Left2Result (operand *left, int offl,
8958                                 operand *result, int offr,
8959                                 int shCount, int sign)
8960 {
8961   int same = pic16_sameRegs(AOP(result), AOP(left));
8962   int i;
8963   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8964
8965   if (same && (offl != offr)) { // shift right bytes
8966     if (offr < offl) {
8967        for(i=0;i<2;i++) {
8968          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8969          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8970        }
8971     } else { // just treat as different later on
8972                 same = 0;
8973     }
8974   }
8975
8976   switch(shCount) {
8977   case 0:
8978     break;
8979   case 1:
8980   case 2:
8981   case 3:
8982     if(sign)
8983       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8984     else
8985       emitCLRC;
8986
8987     if(same) {
8988       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8989       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8990     } else {
8991       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8992       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8993       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8994       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8995     }
8996
8997     while(--shCount) {
8998       if(sign)
8999                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9000       else
9001                 emitCLRC;
9002       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9003       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9004     }
9005     break;
9006   case 4:
9007   case 5:
9008     if(same) {
9009
9010       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9011       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9012       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9013
9014       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9015       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9016       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9017       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9018     } else {
9019       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9020       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9021       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9022
9023       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9024       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9025       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9026       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9027       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9028     }
9029
9030     if(shCount >=5) {
9031       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9032       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9033     }
9034
9035     if(sign) {
9036       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9037       pic16_emitpcode(POC_BTFSC, 
9038                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9039       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9040     }
9041
9042     break;
9043
9044   case 6:
9045     if(same) {
9046
9047       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9048       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9049
9050       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9051       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9052       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9053       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9054       if(sign) {
9055         pic16_emitpcode(POC_BTFSC, 
9056                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9057         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9058       }
9059       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9060       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9061       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9062       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9063     } else {
9064       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9065       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9066       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9067       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9068       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9069       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9070       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9071       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9072       if(sign) {
9073         pic16_emitpcode(POC_BTFSC, 
9074                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9075         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9076       }
9077       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9078       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9079
9080         
9081     }
9082
9083     break;
9084   case 7:
9085     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9086     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9087     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9088     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9089     if(sign) {
9090       emitSKPNC;
9091       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9092     } else 
9093       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9094   }
9095 }
9096
9097
9098 /*-----------------------------------------------------------------*/
9099 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9100 /*-----------------------------------------------------------------*/
9101 static void shiftLLeftOrResult (operand *left, int offl,
9102                                 operand *result, int offr, int shCount)
9103 {
9104     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9105
9106     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9107     /* shift left accumulator */
9108     AccLsh(shCount);
9109     /* or with result */
9110     /* back to result */
9111     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9112 }
9113
9114 /*-----------------------------------------------------------------*/
9115 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9116 /*-----------------------------------------------------------------*/
9117 static void shiftRLeftOrResult (operand *left, int offl,
9118                                 operand *result, int offr, int shCount)
9119 {
9120     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9121     
9122     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9123     /* shift right accumulator */
9124     AccRsh(shCount, 1);
9125     /* or with result */
9126     /* back to result */
9127     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9128 }
9129
9130 /*-----------------------------------------------------------------*/
9131 /* genlshOne - left shift a one byte quantity by known count       */
9132 /*-----------------------------------------------------------------*/
9133 static void genlshOne (operand *result, operand *left, int shCount)
9134 {       
9135     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9136     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9137 }
9138
9139 /*-----------------------------------------------------------------*/
9140 /* genlshTwo - left shift two bytes by known amount != 0           */
9141 /*-----------------------------------------------------------------*/
9142 static void genlshTwo (operand *result,operand *left, int shCount)
9143 {
9144     int size;
9145     
9146     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9147     size = pic16_getDataSize(result);
9148
9149     /* if shCount >= 8 */
9150     if (shCount >= 8) {
9151         shCount -= 8 ;
9152
9153         if (size > 1){
9154             if (shCount)
9155                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9156             else 
9157                 movLeft2Result(left, LSB, result, MSB16);
9158         }
9159         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9160     }
9161
9162     /*  1 <= shCount <= 7 */
9163     else {  
9164         if(size == 1)
9165             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9166         else 
9167             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9168     }
9169 }
9170
9171 /*-----------------------------------------------------------------*/
9172 /* shiftLLong - shift left one long from left to result            */
9173 /* offr = LSB or MSB16                                             */
9174 /*-----------------------------------------------------------------*/
9175 static void shiftLLong (operand *left, operand *result, int offr )
9176 {
9177     int size = AOP_SIZE(result);
9178     int same = pic16_sameRegs(AOP(left),AOP(result));
9179         int i;
9180
9181     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9182
9183         if (same && (offr == MSB16)) { //shift one byte
9184                 for(i=size-1;i>=MSB16;i--) {
9185                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9186                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9187                 }
9188         } else {
9189                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9190         }
9191         
9192     if (size > LSB+offr ){
9193                 if (same) {
9194                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9195                 } else {
9196                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9197                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9198                 }
9199          }
9200
9201     if(size > MSB16+offr){
9202                 if (same) {
9203                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9204                 } else {
9205                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9206                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9207                 }
9208     }
9209
9210     if(size > MSB24+offr){
9211                 if (same) {
9212                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9213                 } else {
9214                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9215                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9216                 }
9217     }
9218
9219     if(size > MSB32+offr){
9220                 if (same) {
9221                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9222                 } else {
9223                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9224                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9225                 }
9226     }
9227     if(offr != LSB)
9228                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9229
9230 }
9231
9232 /*-----------------------------------------------------------------*/
9233 /* genlshFour - shift four byte by a known amount != 0             */
9234 /*-----------------------------------------------------------------*/
9235 static void genlshFour (operand *result, operand *left, int shCount)
9236 {
9237     int size;
9238
9239     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9240     size = AOP_SIZE(result);
9241
9242     /* if shifting more that 3 bytes */
9243     if (shCount >= 24 ) {
9244         shCount -= 24;
9245         if (shCount)
9246             /* lowest order of left goes to the highest
9247             order of the destination */
9248             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9249         else
9250             movLeft2Result(left, LSB, result, MSB32);
9251
9252                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9253                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9254                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9255
9256         return;
9257     }
9258
9259     /* more than two bytes */
9260     else if ( shCount >= 16 ) {
9261         /* lower order two bytes goes to higher order two bytes */
9262         shCount -= 16;
9263         /* if some more remaining */
9264         if (shCount)
9265             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9266         else {
9267             movLeft2Result(left, MSB16, result, MSB32);
9268             movLeft2Result(left, LSB, result, MSB24);
9269         }
9270                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9271                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9272         return;
9273     }    
9274
9275     /* if more than 1 byte */
9276     else if ( shCount >= 8 ) {
9277         /* lower order three bytes goes to higher order  three bytes */
9278         shCount -= 8;
9279         if(size == 2){
9280             if(shCount)
9281                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9282             else
9283                 movLeft2Result(left, LSB, result, MSB16);
9284         }
9285         else{   /* size = 4 */
9286             if(shCount == 0){
9287                 movLeft2Result(left, MSB24, result, MSB32);
9288                 movLeft2Result(left, MSB16, result, MSB24);
9289                 movLeft2Result(left, LSB, result, MSB16);
9290                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9291             }
9292             else if(shCount == 1)
9293                 shiftLLong(left, result, MSB16);
9294             else{
9295                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9296                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9297                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9298                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9299             }
9300         }
9301     }
9302
9303     /* 1 <= shCount <= 7 */
9304     else if(shCount <= 3)
9305     { 
9306         shiftLLong(left, result, LSB);
9307         while(--shCount >= 1)
9308             shiftLLong(result, result, LSB);
9309     }
9310     /* 3 <= shCount <= 7, optimize */
9311     else{
9312         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9313         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9314         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9315     }
9316 }
9317
9318 /*-----------------------------------------------------------------*/
9319 /* genLeftShiftLiteral - left shifting by known count              */
9320 /*-----------------------------------------------------------------*/
9321 void pic16_genLeftShiftLiteral (operand *left,
9322                                  operand *right,
9323                                  operand *result,
9324                                  iCode *ic)
9325 {    
9326     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9327     int size;
9328
9329     FENTRY;
9330     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9331     pic16_freeAsmop(right,NULL,ic,TRUE);
9332
9333     pic16_aopOp(left,ic,FALSE);
9334     pic16_aopOp(result,ic,TRUE);
9335
9336     size = getSize(operandType(result));
9337
9338 #if VIEW_SIZE
9339     pic16_emitcode("; shift left ","result %d, left %d",size,
9340              AOP_SIZE(left));
9341 #endif
9342
9343     /* I suppose that the left size >= result size */
9344     if(shCount == 0){
9345         while(size--){
9346             movLeft2Result(left, size, result, size);
9347         }
9348     }
9349
9350     else if(shCount >= (size * 8))
9351         while(size--)
9352             pic16_aopPut(AOP(result),zero,size);
9353     else{
9354         switch (size) {
9355             case 1:
9356                 genlshOne (result,left,shCount);
9357                 break;
9358
9359             case 2:
9360             case 3:
9361                 genlshTwo (result,left,shCount);
9362                 break;
9363
9364             case 4:
9365                 genlshFour (result,left,shCount);
9366                 break;
9367         }
9368     }
9369     pic16_freeAsmop(left,NULL,ic,TRUE);
9370     pic16_freeAsmop(result,NULL,ic,TRUE);
9371 }
9372
9373 /*-----------------------------------------------------------------*
9374  * genMultiAsm - repeat assembly instruction for size of register.
9375  * if endian == 1, then the high byte (i.e base address + size of 
9376  * register) is used first else the low byte is used first;
9377  *-----------------------------------------------------------------*/
9378 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9379 {
9380
9381   int offset = 0;
9382
9383   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9384
9385   if(!reg)
9386     return;
9387
9388   if(!endian) {
9389     endian = 1;
9390   } else {
9391     endian = -1;
9392     offset = size-1;
9393   }
9394
9395   while(size--) {
9396     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9397     offset += endian;
9398   }
9399
9400 }
9401
9402 #if !(USE_GENERIC_SIGNED_SHIFT)
9403 /*-----------------------------------------------------------------*/
9404 /* genLeftShift - generates code for left shifting                 */
9405 /*-----------------------------------------------------------------*/
9406 static void genLeftShift (iCode *ic)
9407 {
9408   operand *left,*right, *result;
9409   int size, offset;
9410 //  char *l;
9411   symbol *tlbl , *tlbl1;
9412   pCodeOp *pctemp;
9413
9414   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9415
9416   right = IC_RIGHT(ic);
9417   left  = IC_LEFT(ic);
9418   result = IC_RESULT(ic);
9419
9420   pic16_aopOp(right,ic,FALSE);
9421
9422   /* if the shift count is known then do it 
9423      as efficiently as possible */
9424   if (AOP_TYPE(right) == AOP_LIT) {
9425     pic16_genLeftShiftLiteral (left,right,result,ic);
9426     return ;
9427   }
9428
9429   /* shift count is unknown then we have to form
9430    * a loop. Get the loop count in WREG : Note: we take
9431    * only the lower order byte since shifting
9432    * more than 32 bits make no sense anyway, ( the
9433    * largest size of an object can be only 32 bits ) */
9434   
9435   pic16_aopOp(left,ic,FALSE);
9436   pic16_aopOp(result,ic,FALSE);
9437
9438   /* now move the left to the result if they are not the
9439    * same, and if size > 1,
9440    * and if right is not same to result (!!!) -- VR */
9441   if (!pic16_sameRegs(AOP(left),AOP(result))
9442       && (AOP_SIZE(result) > 1)) {
9443
9444     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9445
9446     size = AOP_SIZE(result);
9447     offset=0;
9448     while (size--) {
9449
9450 #if 0
9451       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9452       if (*l == '@' && (IS_AOP_PREG(result))) {
9453
9454           pic16_emitcode("mov","a,%s",l);
9455           pic16_aopPut(AOP(result),"a",offset);
9456       } else
9457 #endif
9458       {
9459         /* we don't know if left is a literal or a register, take care -- VR */
9460         pic16_mov2f(AOP(result), AOP(left), offset);
9461       }
9462       offset++;
9463     }
9464   }
9465
9466   size = AOP_SIZE(result);
9467
9468   /* if it is only one byte then */
9469   if (size == 1) {
9470     if(optimized_for_speed) {
9471       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9472       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9473       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9474       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9475       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9476       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9477       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9478       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9479       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9480       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9481       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9482       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9483     } else {
9484
9485       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9486
9487       tlbl = newiTempLabel(NULL);
9488
9489 #if 1
9490       /* this is already done, why change it? */
9491       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9492                 pic16_mov2f(AOP(result), AOP(left), 0);
9493       }
9494 #endif
9495
9496       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9497       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9498       pic16_emitpLabel(tlbl->key);
9499       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9500       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9501       emitSKPC;
9502       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9503     }
9504     goto release ;
9505   }
9506     
9507   if (pic16_sameRegs(AOP(left),AOP(result))) {
9508
9509     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9510     
9511     tlbl = newiTempLabel(NULL);
9512     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9513     genMultiAsm(POC_RRCF, result, size,1);
9514     pic16_emitpLabel(tlbl->key);
9515     genMultiAsm(POC_RLCF, result, size,0);
9516     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9517     emitSKPC;
9518     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9519     goto release;
9520   }
9521
9522   //tlbl = newiTempLabel(NULL);
9523   //offset = 0 ;   
9524   //tlbl1 = newiTempLabel(NULL);
9525
9526   //reAdjustPreg(AOP(result));    
9527     
9528   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9529   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9530   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9531   //MOVA(l);
9532   //pic16_emitcode("add","a,acc");         
9533   //pic16_aopPut(AOP(result),"a",offset++);
9534   //while (--size) {
9535   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9536   //  MOVA(l);
9537   //  pic16_emitcode("rlc","a");         
9538   //  pic16_aopPut(AOP(result),"a",offset++);
9539   //}
9540   //reAdjustPreg(AOP(result));
9541
9542   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9543   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9544
9545
9546   tlbl = newiTempLabel(NULL);
9547   tlbl1= newiTempLabel(NULL);
9548
9549   size = AOP_SIZE(result);
9550   offset = 1;
9551
9552   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9553
9554   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9555
9556   /* offset should be 0, 1 or 3 */
9557   
9558   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9559   emitSKPNZ;
9560   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9561
9562   pic16_emitpcode(POC_MOVWF, pctemp);
9563
9564
9565   pic16_emitpLabel(tlbl->key);
9566
9567   emitCLRC;
9568   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9569   while(--size)
9570     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9571
9572   pic16_emitpcode(POC_DECFSZ,  pctemp);
9573   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9574   pic16_emitpLabel(tlbl1->key);
9575
9576   pic16_popReleaseTempReg(pctemp,1);
9577
9578
9579  release:
9580   pic16_freeAsmop (right,NULL,ic,TRUE);
9581   pic16_freeAsmop(left,NULL,ic,TRUE);
9582   pic16_freeAsmop(result,NULL,ic,TRUE);
9583 }
9584 #endif
9585
9586
9587 #if 0
9588 #error old code (left here for reference)
9589 /*-----------------------------------------------------------------*/
9590 /* genLeftShift - generates code for left shifting                 */
9591 /*-----------------------------------------------------------------*/
9592 static void genLeftShift (iCode *ic)
9593 {
9594   operand *left,*right, *result;
9595   int size, offset;
9596   char *l;
9597   symbol *tlbl , *tlbl1;
9598   pCodeOp *pctemp;
9599
9600   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9601
9602   right = IC_RIGHT(ic);
9603   left  = IC_LEFT(ic);
9604   result = IC_RESULT(ic);
9605
9606   pic16_aopOp(right,ic,FALSE);
9607
9608   /* if the shift count is known then do it 
9609      as efficiently as possible */
9610   if (AOP_TYPE(right) == AOP_LIT) {
9611     pic16_genLeftShiftLiteral (left,right,result,ic);
9612     return ;
9613   }
9614
9615   /* shift count is unknown then we have to form 
9616      a loop get the loop count in B : Note: we take
9617      only the lower order byte since shifting
9618      more that 32 bits make no sense anyway, ( the
9619      largest size of an object can be only 32 bits ) */  
9620
9621     
9622   pic16_aopOp(left,ic,FALSE);
9623   pic16_aopOp(result,ic,FALSE);
9624
9625   /* now move the left to the result if they are not the
9626      same */
9627   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9628       AOP_SIZE(result) > 1) {
9629
9630     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9631
9632     size = AOP_SIZE(result);
9633     offset=0;
9634     while (size--) {
9635       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9636       if (*l == '@' && (IS_AOP_PREG(result))) {
9637
9638         pic16_emitcode("mov","a,%s",l);
9639         pic16_aopPut(AOP(result),"a",offset);
9640       } else {
9641
9642         /* we don't know if left is a literal or a register, take care -- VR */
9643         pic16_mov2f(AOP(result), AOP(left), offset);
9644       }
9645       offset++;
9646     }
9647   }
9648
9649   size = AOP_SIZE(result);
9650
9651   /* if it is only one byte then */
9652   if (size == 1) {
9653     if(optimized_for_speed) {
9654       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9655       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9656       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9657       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9658       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9659       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9660       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9661       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9662       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9663       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9664       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9665       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9666     } else {
9667
9668       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9669
9670       tlbl = newiTempLabel(NULL);
9671       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9672                 pic16_mov2f(AOP(result), AOP(left), 0);
9673                 
9674 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9675 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9676       }
9677
9678       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9679       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9680       pic16_emitpLabel(tlbl->key);
9681       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9682       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9683       emitSKPC;
9684       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9685     }
9686     goto release ;
9687   }
9688     
9689   if (pic16_sameRegs(AOP(left),AOP(result))) {
9690
9691     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9692     
9693     tlbl = newiTempLabel(NULL);
9694     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9695     genMultiAsm(POC_RRCF, result, size,1);
9696     pic16_emitpLabel(tlbl->key);
9697     genMultiAsm(POC_RLCF, result, size,0);
9698     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9699     emitSKPC;
9700     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9701     goto release;
9702   }
9703
9704   //tlbl = newiTempLabel(NULL);
9705   //offset = 0 ;   
9706   //tlbl1 = newiTempLabel(NULL);
9707
9708   //reAdjustPreg(AOP(result));    
9709     
9710   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9711   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9712   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9713   //MOVA(l);
9714   //pic16_emitcode("add","a,acc");         
9715   //pic16_aopPut(AOP(result),"a",offset++);
9716   //while (--size) {
9717   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9718   //  MOVA(l);
9719   //  pic16_emitcode("rlc","a");         
9720   //  pic16_aopPut(AOP(result),"a",offset++);
9721   //}
9722   //reAdjustPreg(AOP(result));
9723
9724   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9725   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9726
9727
9728   tlbl = newiTempLabel(NULL);
9729   tlbl1= newiTempLabel(NULL);
9730
9731   size = AOP_SIZE(result);
9732   offset = 1;
9733
9734   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9735
9736   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9737
9738   /* offset should be 0, 1 or 3 */
9739   
9740   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9741   emitSKPNZ;
9742   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9743
9744   pic16_emitpcode(POC_MOVWF, pctemp);
9745
9746
9747   pic16_emitpLabel(tlbl->key);
9748
9749   emitCLRC;
9750   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9751   while(--size)
9752     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9753
9754   pic16_emitpcode(POC_DECFSZ,  pctemp);
9755   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9756   pic16_emitpLabel(tlbl1->key);
9757
9758   pic16_popReleaseTempReg(pctemp,1);
9759
9760
9761  release:
9762   pic16_freeAsmop (right,NULL,ic,TRUE);
9763   pic16_freeAsmop(left,NULL,ic,TRUE);
9764   pic16_freeAsmop(result,NULL,ic,TRUE);
9765 }
9766 #endif
9767
9768 /*-----------------------------------------------------------------*/
9769 /* genrshOne - right shift a one byte quantity by known count      */
9770 /*-----------------------------------------------------------------*/
9771 static void genrshOne (operand *result, operand *left,
9772                        int shCount, int sign)
9773 {
9774     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9775     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9776 }
9777
9778 /*-----------------------------------------------------------------*/
9779 /* genrshTwo - right shift two bytes by known amount != 0          */
9780 /*-----------------------------------------------------------------*/
9781 static void genrshTwo (operand *result,operand *left,
9782                        int shCount, int sign)
9783 {
9784   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9785   /* if shCount >= 8 */
9786   if (shCount >= 8) {
9787     shCount -= 8 ;
9788     if (shCount)
9789       shiftR1Left2Result(left, MSB16, result, LSB,
9790                          shCount, sign);
9791     else
9792       movLeft2Result(left, MSB16, result, LSB);
9793
9794     pic16_addSign (result, 1, sign);
9795   }
9796
9797   /*  1 <= shCount <= 7 */
9798   else
9799     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9800 }
9801
9802 /*-----------------------------------------------------------------*/
9803 /* shiftRLong - shift right one long from left to result           */
9804 /* offl = LSB or MSB16                                             */
9805 /*-----------------------------------------------------------------*/
9806 static void shiftRLong (operand *left, int offl,
9807                         operand *result, int sign)
9808 {
9809     int size = AOP_SIZE(result);
9810     int same = pic16_sameRegs(AOP(left),AOP(result));
9811     int i;
9812     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9813
9814         if (same && (offl == MSB16)) { //shift one byte right
9815                 for(i=MSB16;i<size;i++) {
9816                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9817                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9818                 }
9819         }
9820
9821     if(sign)
9822                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9823         else
9824                 emitCLRC;
9825
9826         if (same) {
9827                 if (offl == LSB)
9828                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9829         } else {
9830         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9831         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9832         }
9833
9834     if(offl == MSB16) {
9835         /* add sign of "a" */
9836         pic16_addSign(result, MSB32, sign);
9837         }
9838
9839         if (same) {
9840         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9841         } else {
9842         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9843         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9844         }
9845         
9846         if (same) {
9847         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9848         } else {
9849         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9850         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9851         }
9852
9853         if (same) {
9854         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9855         } else {
9856         if(offl == LSB){
9857                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9858                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9859         }
9860         }
9861 }
9862
9863 /*-----------------------------------------------------------------*/
9864 /* genrshFour - shift four byte by a known amount != 0             */
9865 /*-----------------------------------------------------------------*/
9866 static void genrshFour (operand *result, operand *left,
9867                         int shCount, int sign)
9868 {
9869   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9870   /* if shifting more that 3 bytes */
9871   if(shCount >= 24 ) {
9872     shCount -= 24;
9873     if(shCount)
9874       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9875     else
9876       movLeft2Result(left, MSB32, result, LSB);
9877
9878     pic16_addSign(result, MSB16, sign);
9879   }
9880   else if(shCount >= 16){
9881     shCount -= 16;
9882     if(shCount)
9883       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9884     else{
9885       movLeft2Result(left, MSB24, result, LSB);
9886       movLeft2Result(left, MSB32, result, MSB16);
9887     }
9888     pic16_addSign(result, MSB24, sign);
9889   }
9890   else if(shCount >= 8){
9891     shCount -= 8;
9892     if(shCount == 1)
9893       shiftRLong(left, MSB16, result, sign);
9894     else if(shCount == 0){
9895       movLeft2Result(left, MSB16, result, LSB);
9896       movLeft2Result(left, MSB24, result, MSB16);
9897       movLeft2Result(left, MSB32, result, MSB24);
9898       pic16_addSign(result, MSB32, sign);
9899     }
9900     else{ //shcount >= 2
9901       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9902       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9903       /* the last shift is signed */
9904       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9905       pic16_addSign(result, MSB32, sign);
9906     }
9907   }
9908   else{   /* 1 <= shCount <= 7 */
9909     if(shCount <= 2){
9910       shiftRLong(left, LSB, result, sign);
9911       if(shCount == 2)
9912         shiftRLong(result, LSB, result, sign);
9913     }
9914     else{
9915       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9916       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9917       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9918     }
9919   }
9920 }
9921
9922 /*-----------------------------------------------------------------*/
9923 /* genRightShiftLiteral - right shifting by known count            */
9924 /*-----------------------------------------------------------------*/
9925 static void genRightShiftLiteral (operand *left,
9926                                   operand *right,
9927                                   operand *result,
9928                                   iCode *ic,
9929                                   int sign)
9930 {    
9931   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9932   int lsize,res_size;
9933
9934   pic16_freeAsmop(right,NULL,ic,TRUE);
9935
9936   pic16_aopOp(left,ic,FALSE);
9937   pic16_aopOp(result,ic,TRUE);
9938
9939   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9940
9941 #if VIEW_SIZE
9942   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9943                  AOP_SIZE(left));
9944 #endif
9945
9946   lsize = pic16_getDataSize(left);
9947   res_size = pic16_getDataSize(result);
9948   /* test the LEFT size !!! */
9949
9950   /* I suppose that the left size >= result size */
9951   if(shCount == 0){
9952     assert (res_size <= lsize);
9953     while (res_size--) {
9954       pic16_mov2f (AOP(result), AOP(left), res_size);
9955     } // for
9956   }
9957
9958   else if(shCount >= (lsize * 8)){
9959
9960     if(res_size == 1) {
9961       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9962       if(sign) {
9963         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9964         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
9965       }
9966     } else {
9967
9968       if(sign) {
9969         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
9970         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9971         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9972         while(res_size--)
9973           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
9974
9975       } else {
9976
9977         while(res_size--)
9978           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
9979       }
9980     }
9981   } else {
9982
9983     switch (res_size) {
9984     case 1:
9985       genrshOne (result,left,shCount,sign);
9986       break;
9987
9988     case 2:
9989       genrshTwo (result,left,shCount,sign);
9990       break;
9991
9992     case 4:
9993       genrshFour (result,left,shCount,sign);
9994       break;
9995     default :
9996       break;
9997     }
9998
9999   }
10000
10001   pic16_freeAsmop(left,NULL,ic,TRUE);
10002   pic16_freeAsmop(result,NULL,ic,TRUE);
10003 }
10004
10005 #if !(USE_GENERIC_SIGNED_SHIFT)
10006 /*-----------------------------------------------------------------*/
10007 /* genSignedRightShift - right shift of signed number              */
10008 /*-----------------------------------------------------------------*/
10009 static void genSignedRightShift (iCode *ic)
10010 {
10011   operand *right, *left, *result;
10012   int size, offset;
10013   //  char *l;
10014   symbol *tlbl, *tlbl1 ;
10015   pCodeOp *pctemp;
10016
10017   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10018
10019   /* we do it the hard way put the shift count in b
10020      and loop thru preserving the sign */
10021   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10022
10023   right = IC_RIGHT(ic);
10024   left  = IC_LEFT(ic);
10025   result = IC_RESULT(ic);
10026
10027   pic16_aopOp(right,ic,FALSE);  
10028   pic16_aopOp(left,ic,FALSE);
10029   pic16_aopOp(result,ic,FALSE);
10030
10031
10032   if ( AOP_TYPE(right) == AOP_LIT) {
10033     genRightShiftLiteral (left,right,result,ic,1);
10034     return ;
10035   }
10036   /* shift count is unknown then we have to form 
10037      a loop get the loop count in B : Note: we take
10038      only the lower order byte since shifting
10039      more that 32 bits make no sense anyway, ( the
10040      largest size of an object can be only 32 bits ) */  
10041
10042   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10043   //pic16_emitcode("inc","b");
10044   //pic16_freeAsmop (right,NULL,ic,TRUE);
10045   //pic16_aopOp(left,ic,FALSE);
10046   //pic16_aopOp(result,ic,FALSE);
10047
10048   /* now move the left to the result if they are not the
10049      same */
10050   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10051       AOP_SIZE(result) > 1) {
10052
10053     size = AOP_SIZE(result);
10054     offset=0;
10055     while (size--) { 
10056       /*
10057         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10058         if (*l == '@' && IS_AOP_PREG(result)) {
10059
10060         pic16_emitcode("mov","a,%s",l);
10061         pic16_aopPut(AOP(result),"a",offset);
10062         } else
10063         pic16_aopPut(AOP(result),l,offset);
10064       */
10065       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10066       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10067
10068       offset++;
10069     }
10070   }
10071
10072   /* mov the highest order bit to OVR */    
10073   tlbl = newiTempLabel(NULL);
10074   tlbl1= newiTempLabel(NULL);
10075
10076   size = AOP_SIZE(result);
10077   offset = size - 1;
10078
10079   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10080
10081   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10082
10083   /* offset should be 0, 1 or 3 */
10084   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10085   emitSKPNZ;
10086   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10087
10088   pic16_emitpcode(POC_MOVWF, pctemp);
10089
10090
10091   pic16_emitpLabel(tlbl->key);
10092
10093   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10094   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10095
10096   while(--size) {
10097     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10098   }
10099
10100   pic16_emitpcode(POC_DECFSZ,  pctemp);
10101   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10102   pic16_emitpLabel(tlbl1->key);
10103
10104   pic16_popReleaseTempReg(pctemp,1);
10105 #if 0
10106   size = AOP_SIZE(result);
10107   offset = size - 1;
10108   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10109   pic16_emitcode("rlc","a");
10110   pic16_emitcode("mov","ov,c");
10111   /* if it is only one byte then */
10112   if (size == 1) {
10113     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10114     MOVA(l);
10115     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10116     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10117     pic16_emitcode("mov","c,ov");
10118     pic16_emitcode("rrc","a");
10119     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10120     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10121     pic16_aopPut(AOP(result),"a",0);
10122     goto release ;
10123   }
10124
10125   reAdjustPreg(AOP(result));
10126   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10127   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10128   pic16_emitcode("mov","c,ov");
10129   while (size--) {
10130     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10131     MOVA(l);
10132     pic16_emitcode("rrc","a");         
10133     pic16_aopPut(AOP(result),"a",offset--);
10134   }
10135   reAdjustPreg(AOP(result));
10136   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10137   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10138
10139  release:
10140 #endif
10141
10142   pic16_freeAsmop(left,NULL,ic,TRUE);
10143   pic16_freeAsmop(result,NULL,ic,TRUE);
10144   pic16_freeAsmop(right,NULL,ic,TRUE);
10145 }
10146 #endif
10147
10148 #if !(USE_GENERIC_SIGNED_SHIFT)
10149 #warning This implementation of genRightShift() is incomplete!
10150 /*-----------------------------------------------------------------*/
10151 /* genRightShift - generate code for right shifting                */
10152 /*-----------------------------------------------------------------*/
10153 static void genRightShift (iCode *ic)
10154 {
10155     operand *right, *left, *result;
10156     sym_link *letype ;
10157     int size, offset;
10158     char *l;
10159     symbol *tlbl, *tlbl1 ;
10160
10161     /* if signed then we do it the hard way preserve the
10162     sign bit moving it inwards */
10163     letype = getSpec(operandType(IC_LEFT(ic)));
10164     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10165
10166     if (!SPEC_USIGN(letype)) {
10167         genSignedRightShift (ic);
10168         return ;
10169     }
10170
10171     /* signed & unsigned types are treated the same : i.e. the
10172     signed is NOT propagated inwards : quoting from the
10173     ANSI - standard : "for E1 >> E2, is equivalent to division
10174     by 2**E2 if unsigned or if it has a non-negative value,
10175     otherwise the result is implementation defined ", MY definition
10176     is that the sign does not get propagated */
10177
10178     right = IC_RIGHT(ic);
10179     left  = IC_LEFT(ic);
10180     result = IC_RESULT(ic);
10181
10182     pic16_aopOp(right,ic,FALSE);
10183
10184     /* if the shift count is known then do it 
10185     as efficiently as possible */
10186     if (AOP_TYPE(right) == AOP_LIT) {
10187         genRightShiftLiteral (left,right,result,ic, 0);
10188         return ;
10189     }
10190
10191     /* shift count is unknown then we have to form 
10192     a loop get the loop count in B : Note: we take
10193     only the lower order byte since shifting
10194     more that 32 bits make no sense anyway, ( the
10195     largest size of an object can be only 32 bits ) */  
10196
10197     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10198     pic16_emitcode("inc","b");
10199     pic16_aopOp(left,ic,FALSE);
10200     pic16_aopOp(result,ic,FALSE);
10201
10202     /* now move the left to the result if they are not the
10203     same */
10204     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10205         AOP_SIZE(result) > 1) {
10206
10207         size = AOP_SIZE(result);
10208         offset=0;
10209         while (size--) {
10210             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10211             if (*l == '@' && IS_AOP_PREG(result)) {
10212
10213                 pic16_emitcode("mov","a,%s",l);
10214                 pic16_aopPut(AOP(result),"a",offset);
10215             } else
10216                 pic16_aopPut(AOP(result),l,offset);
10217             offset++;
10218         }
10219     }
10220
10221     tlbl = newiTempLabel(NULL);
10222     tlbl1= newiTempLabel(NULL);
10223     size = AOP_SIZE(result);
10224     offset = size - 1;
10225
10226     /* if it is only one byte then */
10227     if (size == 1) {
10228
10229       tlbl = newiTempLabel(NULL);
10230       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10231         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10232         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10233       }
10234
10235       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10236       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10237       pic16_emitpLabel(tlbl->key);
10238       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10239       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10240       emitSKPC;
10241       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10242
10243       goto release ;
10244     }
10245
10246     reAdjustPreg(AOP(result));
10247     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10248     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10249     CLRC;
10250     while (size--) {
10251         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10252         MOVA(l);
10253         pic16_emitcode("rrc","a");         
10254         pic16_aopPut(AOP(result),"a",offset--);
10255     }
10256     reAdjustPreg(AOP(result));
10257
10258     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10259     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10260
10261 release:
10262     pic16_freeAsmop(left,NULL,ic,TRUE);
10263     pic16_freeAsmop (right,NULL,ic,TRUE);
10264     pic16_freeAsmop(result,NULL,ic,TRUE);
10265 }
10266 #endif
10267
10268 #if (USE_GENERIC_SIGNED_SHIFT)
10269 /*-----------------------------------------------------------------*/
10270 /* genGenericShift - generates code for left or right shifting     */
10271 /*-----------------------------------------------------------------*/
10272 static void genGenericShift (iCode *ic, int isShiftLeft) {
10273   operand *left,*right, *result;
10274   int offset;
10275   int sign, signedCount;
10276   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10277   PIC_OPCODE pos_shift, neg_shift;
10278
10279   FENTRY;
10280
10281   right = IC_RIGHT(ic);
10282   left  = IC_LEFT(ic);
10283   result = IC_RESULT(ic);
10284
10285   pic16_aopOp(right,ic,FALSE);
10286   pic16_aopOp(left,ic,FALSE);
10287   pic16_aopOp(result,ic,TRUE);
10288
10289   sign = !SPEC_USIGN(operandType (left));
10290   signedCount = !SPEC_USIGN(operandType (right));
10291
10292   /* if the shift count is known then do it 
10293      as efficiently as possible */
10294   if (AOP_TYPE(right) == AOP_LIT) {
10295     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10296     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10297     // we should modify right->aopu.aop_lit here!
10298     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10299     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10300     if (isShiftLeft)
10301       pic16_genLeftShiftLiteral (left,right,result,ic);
10302     else
10303       genRightShiftLiteral (left,right,result,ic, sign);
10304
10305     goto release;
10306   } // if (right is literal)
10307
10308   /* shift count is unknown then we have to form a loop.
10309    * Note: we take only the lower order byte since shifting
10310    * more than 32 bits make no sense anyway, ( the
10311    * largest size of an object can be only 32 bits )
10312    * Note: we perform arithmetic shifts if the left operand is
10313    * signed and we do an (effective) right shift, i. e. we
10314    * shift in the sign bit from the left. */
10315    
10316   label_complete = newiTempLabel ( NULL );
10317   label_loop_pos = newiTempLabel ( NULL );
10318   label_loop_neg = NULL;
10319   label_negative = NULL;
10320   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10321   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10322
10323   if (signedCount) {
10324     // additional labels needed
10325     label_loop_neg = newiTempLabel ( NULL );
10326     label_negative = newiTempLabel ( NULL );
10327   } // if
10328
10329   // copy source to result -- this will effectively truncate the left operand to the size of result!
10330   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10331   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10332   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10333     pic16_mov2f (AOP(result),AOP(left), offset);
10334   } // for
10335
10336   // if result is longer than left, fill with zeros (or sign)
10337   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10338     if (sign && AOP_SIZE(left) > 0) {
10339       // shift signed operand -- fill with sign
10340       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10341       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10342       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10343       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10344         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10345       } // for
10346     } else {
10347       // shift unsigned operand -- fill result with zeros
10348       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10349         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10350       } // for
10351     }
10352   } // if (size mismatch)
10353
10354   pic16_mov2w (AOP(right), 0);
10355   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10356   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10357   
10358 #if 0
10359   // perform a shift by one (shift count is positive)
10360   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10361   // 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])
10362   pic16_emitpLabel (label_loop_pos->key);
10363   emitCLRC;
10364   if (sign && (pos_shift == POC_RRCF)) {
10365     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10366     emitSETC;
10367   } // if
10368   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10369   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10370   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10371 #else
10372   // perform a shift by one (shift count is positive)
10373   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10374   // 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])
10375   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10376   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10377   emitCLRC;
10378   pic16_emitpLabel (label_loop_pos->key);
10379   if (sign && (pos_shift == POC_RRCF)) {
10380     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10381     emitSETC;
10382   } // if
10383   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10384   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10385   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10386   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10387 #endif
10388
10389   if (signedCount) {
10390     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10391
10392     pic16_emitpLabel (label_negative->key);
10393     // perform a shift by -1 (shift count is negative)
10394     // 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)
10395     emitCLRC;
10396     pic16_emitpLabel (label_loop_neg->key);
10397     if (sign && (neg_shift == POC_RRCF)) {
10398       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10399       emitSETC;
10400     } // if
10401     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10402     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10403     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10404     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10405   } // if (signedCount)
10406
10407   pic16_emitpLabel (label_complete->key);
10408
10409 release:
10410   pic16_freeAsmop (right,NULL,ic,TRUE);
10411   pic16_freeAsmop(left,NULL,ic,TRUE);
10412   pic16_freeAsmop(result,NULL,ic,TRUE);
10413 }
10414
10415 static void genLeftShift (iCode *ic) {
10416   genGenericShift (ic, 1);
10417 }
10418
10419 static void genRightShift (iCode *ic) {
10420   genGenericShift (ic, 0);
10421 }
10422 #endif
10423
10424
10425 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10426 void pic16_loadFSR0(operand *op, int lit)
10427 {
10428   if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10429     pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10430   } else {
10431     assert (!OP_SYMBOL(op)->remat);
10432     // set up FSR0 with address of result
10433     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10434     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10435   }
10436 }
10437
10438 /*----------------------------------------------------------------*/
10439 /* pic16_derefPtr - move one byte from the location ptr points to */
10440 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10441 /*                  to the location ptr points to (doWrite != 0)   */
10442 /*----------------------------------------------------------------*/
10443 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10444 {
10445   switch (p_type) {
10446     case FPOINTER:
10447     case POINTER:
10448       if (!fsr0_setup || !*fsr0_setup)
10449       {
10450         pic16_loadFSR0( ptr, 0 );
10451         if (fsr0_setup) *fsr0_setup = 1;
10452       }
10453       if (doWrite)
10454         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10455       else
10456         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10457       break;
10458
10459     case GPOINTER:
10460       if (AOP(ptr)->aopu.aop_reg[2]) {
10461         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10462         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10463         pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10464         pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),1), pic16_popCopyReg(&pic16_pc_prodl)));
10465         pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(ptr),2));
10466         pic16_callGenericPointerRW(doWrite, 1);
10467       } else {
10468         // data pointer (just 2 byte given)
10469         if (!fsr0_setup || !*fsr0_setup)
10470         {
10471           pic16_loadFSR0( ptr, 0 );
10472           if (fsr0_setup) *fsr0_setup = 1;
10473         }
10474         if (doWrite)
10475           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10476         else
10477           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10478       }
10479       break;
10480
10481     default:
10482       assert (0 && "invalid pointer type specified");
10483       break;
10484   }
10485 }
10486
10487 /*-----------------------------------------------------------------*/
10488 /* genUnpackBits - generates code for unpacking bits               */
10489 /*-----------------------------------------------------------------*/
10490 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10491 {    
10492   int shCnt ;
10493   sym_link *etype, *letype;
10494   int blen=0, bstr=0;
10495   int lbstr;
10496
10497     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10498     etype = getSpec(operandType(result));
10499     letype = getSpec(operandType(left));
10500     
10501 //    if(IS_BITFIELD(etype)) {
10502       blen = SPEC_BLEN(etype);
10503       bstr = SPEC_BSTR(etype);
10504 //    }
10505
10506     lbstr = SPEC_BSTR( letype );
10507
10508 #if 1
10509     if((blen == 1) && (bstr < 8)) {
10510       /* it is a single bit, so use the appropriate bit instructions */
10511       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10512
10513       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10514       
10515       // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10516       if(!IS_PTR(operandType(left))/* && OP_SYMBOL(left)->remat && (ptype == POINTER)*/) {
10517         /* workaround to reduce the extra lfsr instruction */
10518         pic16_emitpcode(POC_BTFSC,
10519               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10520       } else {
10521         pic16_loadFSR0 (left, 0);
10522         pic16_emitpcode(POC_BTFSC,
10523               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10524       }
10525         
10526       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10527
10528       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10529       return;
10530     }
10531
10532 #endif
10533
10534         /* the following call to pic16_loadFSR0 is temporary until
10535          * optimization to handle single bit assignments is added
10536          * to the function. Until then use the old safe way! -- VR */
10537
10538     if (!IS_PTR(operandType(left)) /*OP_SYMBOL(left)->remat*/) {
10539         // access symbol directly
10540         pic16_mov2w (AOP(left), 0);
10541     } else {
10542       pic16_derefPtr (left, ptype, 0, NULL);
10543     }
10544
10545         /* if we have bitdisplacement then it fits   */
10546         /* into this byte completely or if length is */
10547         /* less than a byte                          */
10548         if ((shCnt = SPEC_BSTR(etype)) || 
10549                 (SPEC_BLEN(etype) <= 8))  {
10550
10551                 /* shift right acc */
10552                 AccRsh(shCnt, 0);
10553
10554                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10555                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10556
10557 /* VR -- normally I would use the following, but since we use the hack,
10558  * to avoid the masking from AccRsh, why not mask it right now? */
10559
10560 /*
10561                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10562 */
10563
10564                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10565           return ;
10566         }
10567
10568
10569
10570         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10571         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10572         exit(-1);
10573
10574     return ;
10575 }
10576
10577
10578 static void genDataPointerGet(operand *left,
10579                               operand *result,
10580                               iCode *ic)
10581 {
10582   int size, offset = 0, leoffset=0 ;
10583
10584         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10585         pic16_aopOp(result, ic, TRUE);
10586
10587         FENTRY;
10588
10589         size = AOP_SIZE(result);
10590 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10591
10592
10593 #if 0
10594         /* The following tests may save a redudant movff instruction when
10595          * accessing unions */
10596          
10597         /* if they are the same */
10598         if (operandsEqu (left, result)) {
10599                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10600                 goto release;
10601         }
10602 #endif
10603
10604 #if 0
10605         /* if they are the same registers */
10606         if (pic16_sameRegs(AOP(left),AOP(result))) {
10607                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10608                 goto release;
10609         }
10610 #endif
10611
10612 #if 1
10613         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10614                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10615                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10616                 goto release;
10617         }
10618 #endif
10619
10620
10621 #if 0
10622         if ( AOP_TYPE(left) == AOP_PCODE) {
10623                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
10624                                 AOP(left)->aopu.pcop->name,
10625                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
10626                                 PCOR(AOP(left)->aopu.pcop)->instance:
10627                                 PCOI(AOP(left)->aopu.pcop)->offset);
10628         }
10629 #endif
10630
10631         if(AOP(left)->aopu.pcop->type == PO_DIR)
10632                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10633
10634         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10635
10636         while (size--) {
10637                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10638                 
10639 //              pic16_DumpOp("(result)",result);
10640                 if(is_LitAOp(AOP(result))) {
10641                         pic16_mov2w(AOP(left), offset); // patch 8
10642                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10643                 } else {
10644                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10645                                 pic16_popGet(AOP(left), offset), //patch 8
10646                                 pic16_popGet(AOP(result), offset)));
10647                 }
10648
10649                 offset++;
10650                 leoffset++;
10651         }
10652
10653 release:
10654     pic16_freeAsmop(result,NULL,ic,TRUE);
10655 }
10656
10657
10658
10659 /*-----------------------------------------------------------------*/
10660 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10661 /*-----------------------------------------------------------------*/
10662 static void genNearPointerGet (operand *left, 
10663                                operand *result, 
10664                                iCode *ic)
10665 {
10666 //  asmop *aop = NULL;
10667   //regs *preg = NULL ;
10668   sym_link *rtype, *retype;
10669   sym_link *ltype, *letype;
10670
10671     FENTRY;
10672     
10673     rtype = operandType(result);
10674     retype= getSpec(rtype);
10675     ltype = operandType(left);
10676     letype= getSpec(ltype);
10677     
10678     pic16_aopOp(left,ic,FALSE);
10679
10680 //    pic16_DumpOp("(left)",left);
10681 //    pic16_DumpOp("(result)",result);
10682
10683     /* if left is rematerialisable and
10684      * result is not bit variable type and
10685      * the left is pointer to data space i.e
10686      * lower 128 bytes of space */
10687     
10688     if (AOP_TYPE(left) == AOP_PCODE
10689       && !IS_BITFIELD(retype)
10690       && DCL_TYPE(ltype) == POINTER) {
10691
10692         genDataPointerGet (left,result,ic);
10693         pic16_freeAsmop(left, NULL, ic, TRUE);
10694         return ;
10695     }
10696     
10697     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10698     pic16_aopOp (result,ic,TRUE);
10699     
10700     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10701
10702 #if 1
10703     if(IS_BITFIELD( retype )
10704       && (SPEC_BLEN(operandType(result))==1)
10705     ) {
10706       iCode *nextic;
10707       pCodeOp *jop;
10708       int bitstrt, bytestrt;
10709
10710         /* if this is bitfield of size 1, see if we are checking the value
10711          * of a single bit in an if-statement,
10712          * if yes, then don't generate usual code, but execute the
10713          * genIfx directly -- VR */
10714
10715         nextic = ic->next;
10716
10717         /* CHECK: if next iCode is IFX
10718          * and current result operand is nextic's conditional operand
10719          * and current result operand live ranges ends at nextic's key number
10720          */
10721         if((nextic->op == IFX)
10722           && (result == IC_COND(nextic))
10723           && (OP_LIVETO(result) == nextic->seq)
10724           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10725           ) {
10726             /* everything is ok then */
10727             /* find a way to optimize the genIfx iCode */
10728
10729             bytestrt = SPEC_BSTR(operandType(result))/8;
10730             bitstrt = SPEC_BSTR(operandType(result))%8;
10731             
10732             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10733
10734             genIfxpCOpJump(nextic, jop);
10735             
10736             pic16_freeAsmop(left, NULL, ic, TRUE);
10737             pic16_freeAsmop(result, NULL, ic, TRUE);
10738             return;
10739         }
10740     }
10741 #endif
10742
10743     /* if bitfield then unpack the bits */
10744     if (IS_BITFIELD(letype)) 
10745       genUnpackBits (result, left, NULL, POINTER);
10746     else {
10747       /* we have can just get the values */
10748       int size = AOP_SIZE(result);
10749       int offset = 0;   
10750         
10751       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10752
10753       pic16_loadFSR0( left, 0 );
10754
10755       while(size--) {
10756         if(size) {
10757           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10758                 pic16_popGet(AOP(result), offset++)));
10759         } else {
10760           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10761                 pic16_popGet(AOP(result), offset++)));
10762         }
10763       }
10764     }
10765
10766 #if 0
10767     /* now some housekeeping stuff */
10768     if (aop) {
10769       /* we had to allocate for this iCode */
10770       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10771       pic16_freeAsmop(NULL,aop,ic,TRUE);
10772     } else { 
10773       /* we did not allocate which means left
10774        * already in a pointer register, then
10775        * if size > 0 && this could be used again
10776        * we have to point it back to where it 
10777        * belongs */
10778       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10779       if (AOP_SIZE(result) > 1
10780         && !OP_SYMBOL(left)->remat
10781         && ( OP_SYMBOL(left)->liveTo > ic->seq
10782             || ic->depth )) {
10783 //        int size = AOP_SIZE(result) - 1;
10784 //        while (size--)
10785 //          pic16_emitcode("dec","%s",rname);
10786         }
10787     }
10788 #endif
10789
10790     /* done */
10791     pic16_freeAsmop(left,NULL,ic,TRUE);
10792     pic16_freeAsmop(result,NULL,ic,TRUE);
10793 }
10794
10795 /*-----------------------------------------------------------------*/
10796 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10797 /*-----------------------------------------------------------------*/
10798 static void genPagedPointerGet (operand *left, 
10799                                operand *result, 
10800                                iCode *ic)
10801 {
10802     asmop *aop = NULL;
10803     regs *preg = NULL ;
10804     char *rname ;
10805     sym_link *rtype, *retype;    
10806
10807     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10808
10809     rtype = operandType(result);
10810     retype= getSpec(rtype);
10811     
10812     pic16_aopOp(left,ic,FALSE);
10813
10814   /* if the value is already in a pointer register
10815        then don't need anything more */
10816     if (!AOP_INPREG(AOP(left))) {
10817         /* otherwise get a free pointer register */
10818         aop = newAsmop(0);
10819         preg = getFreePtr(ic,&aop,FALSE);
10820         pic16_emitcode("mov","%s,%s",
10821                 preg->name,
10822                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10823         rname = preg->name ;
10824     } else
10825         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10826     
10827     pic16_freeAsmop(left,NULL,ic,TRUE);
10828     pic16_aopOp (result,ic,TRUE);
10829
10830     /* if bitfield then unpack the bits */
10831     if (IS_BITFIELD(retype)) 
10832         genUnpackBits (result,left,rname,PPOINTER);
10833     else {
10834         /* we have can just get the values */
10835         int size = AOP_SIZE(result);
10836         int offset = 0 ;        
10837         
10838         while (size--) {
10839             
10840             pic16_emitcode("movx","a,@%s",rname);
10841             pic16_aopPut(AOP(result),"a",offset);
10842             
10843             offset++ ;
10844             
10845             if (size)
10846                 pic16_emitcode("inc","%s",rname);
10847         }
10848     }
10849
10850     /* now some housekeeping stuff */
10851     if (aop) {
10852         /* we had to allocate for this iCode */
10853         pic16_freeAsmop(NULL,aop,ic,TRUE);
10854     } else { 
10855         /* we did not allocate which means left
10856            already in a pointer register, then
10857            if size > 0 && this could be used again
10858            we have to point it back to where it 
10859            belongs */
10860         if (AOP_SIZE(result) > 1 &&
10861             !OP_SYMBOL(left)->remat &&
10862             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10863               ic->depth )) {
10864             int size = AOP_SIZE(result) - 1;
10865             while (size--)
10866                 pic16_emitcode("dec","%s",rname);
10867         }
10868     }
10869
10870     /* done */
10871     pic16_freeAsmop(result,NULL,ic,TRUE);
10872     
10873         
10874 }
10875
10876 #if 0
10877 /* This code is not adjusted to PIC16 and fails utterly.
10878  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10879
10880 /*-----------------------------------------------------------------*/
10881 /* genFarPointerGet - gget value from far space                    */
10882 /*-----------------------------------------------------------------*/
10883 static void genFarPointerGet (operand *left,
10884                               operand *result, iCode *ic)
10885 {
10886     int size, offset ;
10887     sym_link *retype = getSpec(operandType(result));
10888
10889     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10890
10891     pic16_aopOp(left,ic,FALSE);
10892
10893     /* if the operand is already in dptr 
10894     then we do nothing else we move the value to dptr */
10895     if (AOP_TYPE(left) != AOP_STR) {
10896         /* if this is remateriazable */
10897         if (AOP_TYPE(left) == AOP_IMMD)
10898             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10899         else { /* we need to get it byte by byte */
10900             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10901             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10902             if (options.model == MODEL_FLAT24)
10903             {
10904                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10905             }
10906         }
10907     }
10908     /* so dptr know contains the address */
10909     pic16_freeAsmop(left,NULL,ic,TRUE);
10910     pic16_aopOp(result,ic,TRUE);
10911
10912     /* if bit then unpack */
10913     if (IS_BITFIELD(retype)) 
10914         genUnpackBits(result,left,"dptr",FPOINTER);
10915     else {
10916         size = AOP_SIZE(result);
10917         offset = 0 ;
10918
10919         while (size--) {
10920             pic16_emitcode("movx","a,@dptr");
10921             pic16_aopPut(AOP(result),"a",offset++);
10922             if (size)
10923                 pic16_emitcode("inc","dptr");
10924         }
10925     }
10926
10927     pic16_freeAsmop(result,NULL,ic,TRUE);
10928 }
10929 #endif
10930
10931 #if 0
10932 /*-----------------------------------------------------------------*/
10933 /* genCodePointerGet - get value from code space                  */
10934 /*-----------------------------------------------------------------*/
10935 static void genCodePointerGet (operand *left,
10936                                 operand *result, iCode *ic)
10937 {
10938     int size, offset ;
10939     sym_link *retype = getSpec(operandType(result));
10940
10941     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10942
10943     pic16_aopOp(left,ic,FALSE);
10944
10945     /* if the operand is already in dptr 
10946     then we do nothing else we move the value to dptr */
10947     if (AOP_TYPE(left) != AOP_STR) {
10948         /* if this is remateriazable */
10949         if (AOP_TYPE(left) == AOP_IMMD)
10950             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10951         else { /* we need to get it byte by byte */
10952             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10953             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10954             if (options.model == MODEL_FLAT24)
10955             {
10956                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10957             }
10958         }
10959     }
10960     /* so dptr know contains the address */
10961     pic16_freeAsmop(left,NULL,ic,TRUE);
10962     pic16_aopOp(result,ic,FALSE);
10963
10964     /* if bit then unpack */
10965     if (IS_BITFIELD(retype)) 
10966         genUnpackBits(result,left,"dptr",CPOINTER);
10967     else {
10968         size = AOP_SIZE(result);
10969         offset = 0 ;
10970
10971         while (size--) {
10972             pic16_emitcode("clr","a");
10973             pic16_emitcode("movc","a,@a+dptr");
10974             pic16_aopPut(AOP(result),"a",offset++);
10975             if (size)
10976                 pic16_emitcode("inc","dptr");
10977         }
10978     }
10979
10980     pic16_freeAsmop(result,NULL,ic,TRUE);
10981 }
10982 #endif
10983
10984 #if 0
10985 /*-----------------------------------------------------------------*/
10986 /* genGenPointerGet - gget value from generic pointer space        */
10987 /*-----------------------------------------------------------------*/
10988 static void genGenPointerGet (operand *left,
10989                               operand *result, iCode *ic)
10990 {
10991   int size, offset, lit;
10992   sym_link *retype = getSpec(operandType(result));
10993
10994         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10995         pic16_aopOp(left,ic,FALSE);
10996         pic16_aopOp(result,ic,FALSE);
10997         size = AOP_SIZE(result);
10998
10999         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11000
11001         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11002
11003                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11004                 // load FSR0 from immediate
11005                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11006
11007 //              pic16_loadFSR0( left );
11008
11009                 offset = 0;
11010                 while(size--) {
11011                         if(size) {
11012                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11013                         } else {
11014                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11015                         }
11016                         offset++;
11017                 }
11018                 goto release;
11019
11020         }
11021         else { /* we need to get it byte by byte */
11022                 // set up FSR0 with address from left
11023                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11024                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11025                 
11026                 offset = 0 ;
11027
11028                 while(size--) {
11029                         if(size) {
11030                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11031                         } else {
11032                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11033                         }
11034                         offset++;
11035                 }
11036                 goto release;
11037         }
11038
11039   /* if bit then unpack */
11040         if (IS_BITFIELD(retype)) 
11041                 genUnpackBits(result,left,"BAD",GPOINTER);
11042
11043         release:
11044         pic16_freeAsmop(left,NULL,ic,TRUE);
11045         pic16_freeAsmop(result,NULL,ic,TRUE);
11046
11047 }
11048 #endif
11049
11050
11051 /*-----------------------------------------------------------------*/
11052 /* genGenPointerGet - gget value from generic pointer space        */
11053 /*-----------------------------------------------------------------*/
11054 static void genGenPointerGet (operand *left,
11055                               operand *result, iCode *ic)
11056 {
11057   int size, offset, lit;
11058   sym_link *letype = getSpec(operandType(left));
11059
11060     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11061     pic16_aopOp(left,ic,FALSE);
11062     pic16_aopOp(result,ic,TRUE);
11063     size = AOP_SIZE(result);
11064
11065     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11066   
11067     /* if bit then unpack */
11068     if (IS_BITFIELD(letype)) {
11069       genUnpackBits(result,left,"BAD",GPOINTER);
11070       goto release;
11071     }
11072
11073     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11074
11075       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11076       // load FSR0 from immediate
11077       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11078
11079       werror(W_POSSBUG2, __FILE__, __LINE__);
11080
11081       offset = 0;
11082       while(size--) {
11083         if(size) {
11084           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11085         } else {
11086           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11087         }
11088         offset++;
11089       }
11090
11091       goto release;
11092
11093     } else { /* we need to get it byte by byte */
11094
11095       /* set up WREG:PRODL:FSR0L with address from left */
11096       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11097       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11098       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11099       
11100       pic16_callGenericPointerRW(0, size);
11101       
11102       assignResultValue(result, 1);
11103       
11104       goto release;
11105     }
11106
11107 release:
11108   pic16_freeAsmop(left,NULL,ic,TRUE);
11109   pic16_freeAsmop(result,NULL,ic,TRUE);
11110 }
11111
11112 /*-----------------------------------------------------------------*/
11113 /* genConstPointerGet - get value from const generic pointer space */
11114 /*-----------------------------------------------------------------*/
11115 static void genConstPointerGet (operand *left,
11116                                 operand *result, iCode *ic)
11117 {
11118   //sym_link *retype = getSpec(operandType(result));
11119   // symbol *albl = newiTempLabel(NULL);        // patch 15
11120   // symbol *blbl = newiTempLabel(NULL);        //
11121   // PIC_OPCODE poc;                            // patch 15
11122   int size;
11123   int offset = 0;
11124
11125   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11126   pic16_aopOp(left,ic,FALSE);
11127   pic16_aopOp(result,ic,TRUE);
11128   size = AOP_SIZE(result);
11129
11130   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11131
11132   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11133
11134   // set up table pointer
11135   if( (AOP_TYPE(left) == AOP_PCODE) 
11136       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11137           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11138     {
11139       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11140       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11141       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11142       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11143       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11144       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11145   } else {
11146     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11147     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11148     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11149   }
11150
11151   while(size--) {
11152     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11153     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11154     offset++;
11155   }
11156     
11157   pic16_freeAsmop(left,NULL,ic,TRUE);
11158   pic16_freeAsmop(result,NULL,ic,TRUE);
11159 }
11160
11161
11162 /*-----------------------------------------------------------------*/
11163 /* genPointerGet - generate code for pointer get                   */
11164 /*-----------------------------------------------------------------*/
11165 static void genPointerGet (iCode *ic)
11166 {
11167   operand *left, *result ;
11168   sym_link *type, *etype;
11169   int p_type;
11170
11171     FENTRY;
11172     
11173     left = IC_LEFT(ic);
11174     result = IC_RESULT(ic) ;
11175
11176     /* depending on the type of pointer we need to
11177     move it to the correct pointer register */
11178     type = operandType(left);
11179     etype = getSpec(type);
11180
11181 #if 0
11182     if (IS_PTR_CONST(type))
11183 #else
11184     if (IS_CODEPTR(type))
11185 #endif
11186       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11187
11188     /* if left is of type of pointer then it is simple */
11189     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11190       p_type = DCL_TYPE(type);
11191     else {
11192       /* we have to go by the storage class */
11193       p_type = PTR_TYPE(SPEC_OCLS(etype));
11194
11195       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11196
11197       if (SPEC_OCLS(etype)->codesp ) {
11198         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11199         //p_type = CPOINTER ;   
11200       } else
11201       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11202         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11203         /*p_type = FPOINTER ;*/ 
11204       } else
11205       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11206         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11207         /* p_type = PPOINTER; */
11208       } else
11209       if (SPEC_OCLS(etype) == idata ) {
11210         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11211         /* p_type = IPOINTER; */
11212       } else {
11213         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11214         /* p_type = POINTER ; */
11215       }
11216     }
11217
11218     /* now that we have the pointer type we assign
11219     the pointer values */
11220     switch (p_type) {
11221       case POINTER:     
11222       case FPOINTER:
11223       case IPOINTER:
11224         genNearPointerGet (left,result,ic);
11225         break;
11226
11227       case PPOINTER:
11228         genPagedPointerGet(left,result,ic);
11229         break;
11230
11231 #if 0
11232       /* PICs do not support FAR pointers... */
11233       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11234       case FPOINTER:
11235         genFarPointerGet (left,result,ic);
11236         break;
11237 #endif
11238
11239       case CPOINTER:
11240         genConstPointerGet (left,result,ic);
11241         //pic16_emitcodePointerGet (left,result,ic);
11242         break;
11243
11244       case GPOINTER:
11245 #if 0
11246       if (IS_PTR_CONST(type))
11247         genConstPointerGet (left,result,ic);
11248       else
11249 #endif
11250         genGenPointerGet (left,result,ic);
11251       break;
11252
11253     default:
11254       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11255               "genPointerGet: illegal pointer type");
11256     
11257     }
11258 }
11259
11260 /*-----------------------------------------------------------------*/
11261 /* genPackBits - generates code for packed bit storage             */
11262 /*-----------------------------------------------------------------*/
11263 static void genPackBits (sym_link    *etype , operand *result,
11264                          operand *right ,
11265                          char *rname, int p_type)
11266 {
11267   int shCnt = 0 ;
11268   int offset = 0  ;
11269   int rLen = 0 ;
11270   int blen, bstr ;   
11271   sym_link *retype;
11272
11273         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11274         blen = SPEC_BLEN(etype);
11275         bstr = SPEC_BSTR(etype);
11276
11277         retype = getSpec(operandType(right));
11278
11279         if(AOP_TYPE(right) == AOP_LIT) {
11280                 if((blen == 1) && (bstr < 8)) {
11281                   unsigned long lit;
11282                         /* it is a single bit, so use the appropriate bit instructions */
11283
11284                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11285
11286                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11287 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11288                         if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11289                                 /* workaround to reduce the extra lfsr instruction */
11290                                 if(lit) {
11291                                         pic16_emitpcode(POC_BSF,
11292                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11293                                 } else {
11294                                         pic16_emitpcode(POC_BCF,
11295                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11296                                 }
11297                         } else {
11298                                 pic16_loadFSR0(result, 0);
11299                                 if(lit) {
11300                                         pic16_emitpcode(POC_BSF,
11301                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11302                                 } else {
11303                                         pic16_emitpcode(POC_BCF,
11304                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11305                                 }
11306                         }
11307         
11308                   return;
11309                 }
11310                 /* move literal to W */
11311                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11312                 offset++;
11313         } else
11314         if(IS_BITFIELD(retype) 
11315           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11316           && (blen == 1)) {
11317           int rblen, rbstr;
11318
11319             rblen = SPEC_BLEN( retype );
11320             rbstr = SPEC_BSTR( retype );
11321             
11322
11323             if(IS_BITFIELD(etype)) {
11324               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11325               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11326             } else {
11327               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11328             }
11329             
11330             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11331             
11332             if(IS_BITFIELD(etype)) {
11333               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11334             } else {
11335               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11336             }
11337
11338             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11339             
11340             return;
11341         } else {
11342           /* move right to W */
11343           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11344         }
11345
11346         /* if the bit length is less than or   */
11347         /* it exactly fits a byte then         */
11348         if((shCnt=SPEC_BSTR(etype))
11349                 || SPEC_BLEN(etype) <= 8 )  {
11350                 int fsr0_setup = 0;
11351
11352                 if (blen != 8 || bstr != 0) {
11353                   // we need to combine the value with the old value
11354                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11355
11356           DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11357                 SPEC_BSTR(etype), SPEC_BLEN(etype));
11358                 
11359                   /* shift left acc */
11360                   AccLsh(shCnt);
11361
11362                   /* using PRODH as a temporary register here */
11363                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11364
11365                   if (IS_SYMOP(result) && !IS_PTR(operandType (result))/*OP_SYMBOL(result)->remat*/) {
11366                     /* access symbol directly */
11367                     pic16_mov2w (AOP(result), 0);
11368                   } else {
11369                     /* get old value */
11370                     pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11371                   }
11372 #if 1
11373                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11374                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11375                                         (unsigned char)(0xff >> (8-bstr))) ));
11376                   pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11377                 } // if (blen != 8 || bstr != 0)
11378
11379                 /* write new value back */
11380                 if (IS_SYMOP(result) & !IS_PTR(operandType(result))) {
11381                   pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11382                 } else {
11383                   pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11384                }
11385 #endif
11386
11387           return;
11388         }
11389
11390
11391 #if 0
11392         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11393         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11394         exit(-1);
11395 #endif
11396
11397
11398     pic16_loadFSR0(result, 0);                  // load FSR0 with address of result
11399     rLen = SPEC_BLEN(etype)-8;
11400     
11401     /* now generate for lengths greater than one byte */
11402     while (1) {
11403         rLen -= 8 ;
11404         if (rLen <= 0 ) {
11405           mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11406           break ;
11407         }
11408
11409         switch (p_type) {
11410             case POINTER:
11411                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11412                 break;
11413
11414 /*
11415             case FPOINTER:
11416                 MOVA(l);
11417                 pic16_emitcode("movx","@dptr,a");
11418                 break;
11419
11420             case GPOINTER:
11421                 MOVA(l);
11422                 DEBUGpic16_emitcode(";lcall","__gptrput");
11423                 break;  
11424 */
11425           default:
11426             assert(0);
11427         }   
11428
11429
11430         pic16_mov2w(AOP(right), offset++);
11431     }
11432
11433     /* last last was not complete */
11434     if (rLen)   {
11435         /* save the byte & read byte */
11436         switch (p_type) {
11437             case POINTER:
11438 //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11439                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11440                 break;
11441
11442 /*
11443             case FPOINTER:
11444                 pic16_emitcode ("mov","b,a");
11445                 pic16_emitcode("movx","a,@dptr");
11446                 break;
11447
11448             case GPOINTER:
11449                 pic16_emitcode ("push","b");
11450                 pic16_emitcode ("push","acc");
11451                 pic16_emitcode ("lcall","__gptrget");
11452                 pic16_emitcode ("pop","b");
11453                 break;
11454 */
11455             default:
11456               assert(0);
11457         }
11458         DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11459         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11460         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11461 //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11462 //        pic16_emitcode ("orl","a,b");
11463     }
11464
11465 //    if (p_type == GPOINTER)
11466 //        pic16_emitcode("pop","b");
11467
11468     switch (p_type) {
11469
11470       case POINTER:
11471         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11472 //      pic16_emitcode("mov","@%s,a",rname);
11473         break;
11474 /*
11475       case FPOINTER:
11476         pic16_emitcode("movx","@dptr,a");
11477         break;
11478         
11479       case GPOINTER:
11480         DEBUGpic16_emitcode(";lcall","__gptrput");
11481         break;                  
11482 */
11483       default:
11484         assert(0);
11485     }
11486     
11487 //    pic16_freeAsmop(right, NULL, ic, TRUE);
11488 }
11489 /*-----------------------------------------------------------------*/
11490 /* genDataPointerSet - remat pointer to data space                 */
11491 /*-----------------------------------------------------------------*/
11492 static void genDataPointerSet(operand *right,
11493                               operand *result,
11494                               iCode *ic)
11495 {
11496     int size, offset = 0, resoffset=0 ;
11497
11498     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11499     pic16_aopOp(right,ic,FALSE);
11500
11501     size = AOP_SIZE(right);
11502
11503 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11504
11505 #if 0
11506     if ( AOP_TYPE(result) == AOP_PCODE) {
11507       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11508               AOP(result)->aopu.pcop->name,
11509                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11510               PCOR(AOP(result)->aopu.pcop)->instance:
11511               PCOI(AOP(result)->aopu.pcop)->offset);
11512     }
11513 #endif
11514
11515         if(AOP(result)->aopu.pcop->type == PO_DIR)
11516                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11517
11518         while (size--) {
11519                 if (AOP_TYPE(right) == AOP_LIT) {
11520                   unsigned int lit;
11521
11522                     if(!IS_FLOAT(operandType( right )))
11523                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11524                     else {
11525                       union {
11526                         unsigned long lit_int;
11527                         float lit_float;
11528                       } info;
11529         
11530                         /* take care if literal is a float */
11531                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11532                         lit = info.lit_int;
11533                     }
11534
11535                     lit = lit >> (8*offset);
11536                     if(lit&0xff) {
11537                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11538                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11539                     } else {
11540                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11541                     }
11542                 } else {
11543                   pic16_mov2w(AOP(right), offset);
11544                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11545                 }
11546                 offset++;
11547                 resoffset++;
11548         }
11549
11550     pic16_freeAsmop(right,NULL,ic,TRUE);
11551 }
11552
11553
11554
11555 /*-----------------------------------------------------------------*/
11556 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11557 /*-----------------------------------------------------------------*/
11558 static void genNearPointerSet (operand *right,
11559                                operand *result, 
11560                                iCode *ic)
11561 {
11562   asmop *aop = NULL;
11563   sym_link *retype;
11564   sym_link *ptype = operandType(result);
11565   sym_link *resetype;
11566     
11567         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11568         retype= getSpec(operandType(right));
11569         resetype = getSpec(operandType(result));
11570   
11571         pic16_aopOp(result,ic,FALSE);
11572     
11573         /* if the result is rematerializable &
11574          * in data space & not a bit variable */
11575         
11576         /* and result is not a bit variable */
11577         if (AOP_TYPE(result) == AOP_PCODE
11578 //              && AOP_TYPE(result) == AOP_IMMD
11579                 && DCL_TYPE(ptype) == POINTER
11580                 && !IS_BITFIELD(retype)
11581                 && !IS_BITFIELD(resetype)) {
11582
11583                 genDataPointerSet (right,result,ic);
11584                 pic16_freeAsmop(result,NULL,ic,TRUE);
11585           return;
11586         }
11587
11588         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11589         pic16_aopOp(right,ic,FALSE);
11590         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11591
11592         /* if bitfield then unpack the bits */
11593         if (IS_BITFIELD(resetype)) {
11594                 genPackBits (resetype, result, right, NULL, POINTER);
11595         } else {
11596                 /* we have can just get the values */
11597           int size = AOP_SIZE(right);
11598           int offset = 0 ;    
11599
11600             pic16_loadFSR0(result, 0);
11601             
11602                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11603                 while (size--) {
11604                                 if (AOP_TYPE(right) == AOP_LIT) {
11605                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11606                                         if (size) {
11607                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11608                                         } else {
11609                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11610                                         }
11611                                 } else { // no literal
11612                                         if(size) {
11613                                                 pic16_emitpcode(POC_MOVFF,
11614                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11615                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11616                                         } else {
11617                                                 pic16_emitpcode(POC_MOVFF,
11618                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11619                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11620                                         }
11621                                 }
11622                         offset++;
11623                 }
11624         }
11625
11626         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11627         /* now some housekeeping stuff */
11628         if (aop) {
11629           /* we had to allocate for this iCode */
11630           pic16_freeAsmop(NULL,aop,ic,TRUE);
11631         } else { 
11632           /* we did not allocate which means left
11633            * already in a pointer register, then
11634            * if size > 0 && this could be used again
11635            * we have to point it back to where it 
11636            * belongs */
11637           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11638           if (AOP_SIZE(right) > 1
11639             && !OP_SYMBOL(result)->remat
11640             && ( OP_SYMBOL(result)->liveTo > ic->seq
11641             || ic->depth )) {
11642
11643               int size = AOP_SIZE(right) - 1;
11644
11645                 while (size--)
11646                   pic16_emitcode("decf","fsr0,f");
11647                   //pic16_emitcode("dec","%s",rname);
11648             }
11649         }
11650
11651     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11652     /* done */
11653 //release:
11654     pic16_freeAsmop(right,NULL,ic,TRUE);
11655     pic16_freeAsmop(result,NULL,ic,TRUE);
11656 }
11657
11658 /*-----------------------------------------------------------------*/
11659 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11660 /*-----------------------------------------------------------------*/
11661 static void genPagedPointerSet (operand *right,
11662                                operand *result, 
11663                                iCode *ic)
11664 {
11665     asmop *aop = NULL;
11666     regs *preg = NULL ;
11667     char *rname , *l;
11668     sym_link *retype;
11669        
11670     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11671
11672     retype= getSpec(operandType(right));
11673     
11674     pic16_aopOp(result,ic,FALSE);
11675     
11676     /* if the value is already in a pointer register
11677        then don't need anything more */
11678     if (!AOP_INPREG(AOP(result))) {
11679         /* otherwise get a free pointer register */
11680         aop = newAsmop(0);
11681         preg = getFreePtr(ic,&aop,FALSE);
11682         pic16_emitcode("mov","%s,%s",
11683                 preg->name,
11684                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11685         rname = preg->name ;
11686     } else
11687         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11688     
11689     pic16_freeAsmop(result,NULL,ic,TRUE);
11690     pic16_aopOp (right,ic,FALSE);
11691
11692     /* if bitfield then unpack the bits */
11693     if (IS_BITFIELD(retype)) 
11694         genPackBits (retype,result,right,rname,PPOINTER);
11695     else {
11696         /* we have can just get the values */
11697         int size = AOP_SIZE(right);
11698         int offset = 0 ;        
11699         
11700         while (size--) {
11701             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11702             
11703             MOVA(l);
11704             pic16_emitcode("movx","@%s,a",rname);
11705
11706             if (size)
11707                 pic16_emitcode("inc","%s",rname);
11708
11709             offset++;
11710         }
11711     }
11712     
11713     /* now some housekeeping stuff */
11714     if (aop) {
11715         /* we had to allocate for this iCode */
11716         pic16_freeAsmop(NULL,aop,ic,TRUE);
11717     } else { 
11718         /* we did not allocate which means left
11719            already in a pointer register, then
11720            if size > 0 && this could be used again
11721            we have to point it back to where it 
11722            belongs */
11723         if (AOP_SIZE(right) > 1 &&
11724             !OP_SYMBOL(result)->remat &&
11725             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11726               ic->depth )) {
11727             int size = AOP_SIZE(right) - 1;
11728             while (size--)
11729                 pic16_emitcode("dec","%s",rname);
11730         }
11731     }
11732
11733     /* done */
11734     pic16_freeAsmop(right,NULL,ic,TRUE);
11735     
11736         
11737 }
11738
11739 #if 0
11740 /* This code is not adjusted to PIC16 and fails utterly...
11741  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11742
11743 /*-----------------------------------------------------------------*/
11744 /* genFarPointerSet - set value from far space                     */
11745 /*-----------------------------------------------------------------*/
11746 static void genFarPointerSet (operand *right,
11747                               operand *result, iCode *ic)
11748 {
11749     int size, offset ;
11750     sym_link *retype = getSpec(operandType(right));
11751
11752     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11753     pic16_aopOp(result,ic,FALSE);
11754
11755     /* if the operand is already in dptr 
11756     then we do nothing else we move the value to dptr */
11757     if (AOP_TYPE(result) != AOP_STR) {
11758         /* if this is remateriazable */
11759         if (AOP_TYPE(result) == AOP_IMMD)
11760             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11761         else { /* we need to get it byte by byte */
11762             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11763             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11764             if (options.model == MODEL_FLAT24)
11765             {
11766                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11767             }
11768         }
11769     }
11770     /* so dptr know contains the address */
11771     pic16_freeAsmop(result,NULL,ic,TRUE);
11772     pic16_aopOp(right,ic,FALSE);
11773
11774     /* if bit then unpack */
11775     if (IS_BITFIELD(retype)) 
11776         genPackBits(retype,result,right,"dptr",FPOINTER);
11777     else {
11778         size = AOP_SIZE(right);
11779         offset = 0 ;
11780
11781         while (size--) {
11782             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11783             MOVA(l);
11784             pic16_emitcode("movx","@dptr,a");
11785             if (size)
11786                 pic16_emitcode("inc","dptr");
11787         }
11788     }
11789
11790     pic16_freeAsmop(right,NULL,ic,TRUE);
11791 }
11792 #endif
11793
11794 /*-----------------------------------------------------------------*/
11795 /* genGenPointerSet - set value from generic pointer space         */
11796 /*-----------------------------------------------------------------*/
11797 #if 0
11798 static void genGenPointerSet (operand *right,
11799                               operand *result, iCode *ic)
11800 {
11801         int i, size, offset, lit;
11802         sym_link *retype = getSpec(operandType(right));
11803
11804         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11805
11806         pic16_aopOp(result,ic,FALSE);
11807         pic16_aopOp(right,ic,FALSE);
11808         size = AOP_SIZE(right);
11809         offset = 0;
11810
11811         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11812
11813         /* if the operand is already in dptr 
11814                 then we do nothing else we move the value to dptr */
11815         if (AOP_TYPE(result) != AOP_STR) {
11816                 /* if this is remateriazable */
11817                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11818                 // WARNING: anythig until "else" is untested!
11819                 if (AOP_TYPE(result) == AOP_IMMD) {
11820                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11821                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11822                         // load FSR0 from immediate
11823                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11824                         offset = 0;
11825                         while(size--) {
11826                                 if(size) {
11827                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11828                                 } else {
11829                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11830                                 }
11831                                 offset++;
11832                         }
11833                         goto release;
11834                 }
11835                 else { /* we need to get it byte by byte */
11836                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11837                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11838
11839                         // set up FSR0 with address of result
11840                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11841                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11842
11843                         /* hack hack! see if this the FSR. If so don't load W */
11844                         if(AOP_TYPE(right) != AOP_ACC) {
11845
11846                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11847
11848                                 if(AOP_TYPE(right) == AOP_LIT)
11849                                 {
11850                                         // copy literal
11851                                         // note: pic16_popGet handles sign extension
11852                                         for(i=0;i<size;i++) {
11853                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11854                                                 if(i < size-1)
11855                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11856                                                 else
11857                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11858                                         }
11859                                 } else {
11860                                         // copy regs
11861
11862                                         for(i=0;i<size;i++) {
11863                                                 if(i < size-1)
11864                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11865                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11866                                                 else
11867                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11868                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11869                                         }
11870                                 }
11871                                 goto release;
11872                         } 
11873                         // right = ACC
11874                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11875                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11876                         goto release;
11877         } // if (AOP_TYPE(result) != AOP_IMMD)
11878
11879         } // if (AOP_TYPE(result) != AOP_STR)
11880         /* so dptr know contains the address */
11881
11882
11883         /* if bit then unpack */
11884         if (IS_BITFIELD(retype)) 
11885                 genPackBits(retype,result,right,"dptr",GPOINTER);
11886         else {
11887                 size = AOP_SIZE(right);
11888                 offset = 0 ;
11889
11890                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11891
11892                 // set up FSR0 with address of result
11893                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11894                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11895         
11896                 while (size--) {
11897                         if (AOP_TYPE(right) == AOP_LIT) {
11898                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11899                                 if (size) {
11900                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11901                                 } else {
11902                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11903                                 }
11904                         } else { // no literal
11905                                 if(size) {
11906                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11907                                 } else {
11908                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11909                                 }
11910                         }
11911                         offset++;
11912                 }
11913         }
11914
11915         release:
11916         pic16_freeAsmop(right,NULL,ic,TRUE);
11917         pic16_freeAsmop(result,NULL,ic,TRUE);
11918 }
11919 #endif
11920
11921 static void genGenPointerSet (operand *right,
11922                               operand *result, iCode *ic)
11923 {
11924   int size;
11925   sym_link *retype = getSpec(operandType(result));
11926
11927     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11928
11929     pic16_aopOp(result,ic,FALSE);
11930     pic16_aopOp(right,ic,FALSE);
11931     size = AOP_SIZE(right);
11932
11933     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11934
11935
11936     /* if bit then unpack */
11937     if (IS_BITFIELD(retype)) {
11938 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11939       genPackBits(retype,result,right,"dptr",GPOINTER);
11940       goto release;
11941     }
11942
11943     size = AOP_SIZE(right);
11944
11945     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11946
11947
11948     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
11949
11950     /* value of right+0 is placed on stack, which will be retrieved
11951      * by the support function this restoring the stack. The important
11952      * thing is that there is no need to manually restore stack pointer
11953      * here */
11954     pushaop(AOP(right), 0);
11955 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
11956     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
11957     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
11958     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
11959     
11960     /* load address to write to in WREG:FSR0H:FSR0L */
11961     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
11962                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
11963     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
11964                                 pic16_popCopyReg(&pic16_pc_prodl)));
11965     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
11966     
11967     pic16_callGenericPointerRW(1, size);
11968
11969 release:
11970     pic16_freeAsmop(right,NULL,ic,TRUE);
11971     pic16_freeAsmop(result,NULL,ic,TRUE);
11972 }
11973
11974 /*-----------------------------------------------------------------*/
11975 /* genPointerSet - stores the value into a pointer location        */
11976 /*-----------------------------------------------------------------*/
11977 static void genPointerSet (iCode *ic)
11978 {    
11979   operand *right, *result ;
11980   sym_link *type, *etype;
11981   int p_type;
11982
11983     FENTRY;
11984
11985     right = IC_RIGHT(ic);
11986     result = IC_RESULT(ic) ;
11987
11988     /* depending on the type of pointer we need to
11989     move it to the correct pointer register */
11990     type = operandType(result);
11991     etype = getSpec(type);
11992     
11993     /* if left is of type of pointer then it is simple */
11994     if (IS_PTR(type) && !IS_FUNC(type->next)) {
11995         p_type = DCL_TYPE(type);
11996     }
11997     else {
11998         /* we have to go by the storage class */
11999         p_type = PTR_TYPE(SPEC_OCLS(etype));
12000
12001 /*      if (SPEC_OCLS(etype)->codesp ) { */
12002 /*          p_type = CPOINTER ;  */
12003 /*      } */
12004 /*      else */
12005 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12006 /*              p_type = FPOINTER ; */
12007 /*          else */
12008 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12009 /*                  p_type = PPOINTER ; */
12010 /*              else */
12011 /*                  if (SPEC_OCLS(etype) == idata ) */
12012 /*                      p_type = IPOINTER ; */
12013 /*                  else */
12014 /*                      p_type = POINTER ; */
12015     }
12016
12017     /* now that we have the pointer type we assign
12018     the pointer values */
12019     switch (p_type) {
12020       case POINTER:
12021       case FPOINTER:
12022       case IPOINTER:
12023         genNearPointerSet (right,result,ic);
12024         break;
12025
12026       case PPOINTER:
12027         genPagedPointerSet (right,result,ic);
12028         break;
12029
12030 #if 0
12031       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12032       case FPOINTER:
12033         genFarPointerSet (right,result,ic);
12034         break;
12035 #endif
12036         
12037       case GPOINTER:
12038         genGenPointerSet (right,result,ic);
12039         break;
12040
12041       default:
12042         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12043           "genPointerSet: illegal pointer type");
12044     }
12045 }
12046
12047 /*-----------------------------------------------------------------*/
12048 /* genIfx - generate code for Ifx statement                        */
12049 /*-----------------------------------------------------------------*/
12050 static void genIfx (iCode *ic, iCode *popIc)
12051 {
12052   operand *cond = IC_COND(ic);
12053   int isbit =0;
12054
12055     FENTRY;
12056
12057     pic16_aopOp(cond,ic,FALSE);
12058
12059     /* get the value into acc */
12060     if (AOP_TYPE(cond) != AOP_CRY)
12061       pic16_toBoolean(cond);
12062     else
12063       isbit = 1;
12064     /* the result is now in the accumulator */
12065     pic16_freeAsmop(cond,NULL,ic,TRUE);
12066
12067     /* if there was something to be popped then do it */
12068     if (popIc)
12069       genIpop(popIc);
12070
12071     /* if the condition is  a bit variable */
12072     if (isbit && IS_ITEMP(cond) && 
12073         SPIL_LOC(cond)) {
12074       genIfxJump(ic,"c");
12075       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12076     } else {
12077       if (isbit && !IS_ITEMP(cond))
12078         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12079         else
12080         genIfxJump(ic,"a");
12081     }
12082     ic->generated = 1;
12083 }
12084
12085 /*-----------------------------------------------------------------*/
12086 /* genAddrOf - generates code for address of                       */
12087 /*-----------------------------------------------------------------*/
12088 static void genAddrOf (iCode *ic)
12089 {
12090   operand *result, *left;
12091   int size;
12092   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12093   pCodeOp *pcop0, *pcop1, *pcop2;
12094
12095     FENTRY;
12096
12097     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12098
12099     sym = OP_SYMBOL( IC_LEFT(ic) );
12100     
12101     if(sym->onStack) {
12102       /* get address of symbol on stack */
12103       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12104 #if 0
12105       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12106                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12107 #endif
12108
12109       // operands on stack are accessible via "FSR2 + index" with index
12110       // starting at 2 for arguments and growing from 0 downwards for
12111       // local variables (index == 0 is not assigned so we add one here)
12112       {
12113         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12114         if (soffs <= 0) {
12115           assert (soffs < 0);
12116           soffs++;
12117         } // if
12118         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12119         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12120         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12121         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12122         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12123         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12124         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12125       }
12126
12127       goto release;
12128     }
12129         
12130 //      if(pic16_debug_verbose) {
12131 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12132 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12133 //      }
12134         
12135     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12136     size = AOP_SIZE(IC_RESULT(ic));
12137
12138     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12139     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12140     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12141         
12142     if (size == 3) {
12143       pic16_emitpcode(POC_MOVLW, pcop0);
12144       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12145       pic16_emitpcode(POC_MOVLW, pcop1);
12146       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12147       pic16_emitpcode(POC_MOVLW, pcop2);
12148       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12149     } else
12150     if (size == 2) {
12151       pic16_emitpcode(POC_MOVLW, pcop0);
12152       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12153       pic16_emitpcode(POC_MOVLW, pcop1);
12154     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12155     } else {
12156       pic16_emitpcode(POC_MOVLW, pcop0);
12157       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12158     }
12159
12160     pic16_freeAsmop(left, NULL, ic, FALSE);
12161 release:
12162     pic16_freeAsmop(result,NULL,ic,TRUE);
12163 }
12164
12165
12166 #if 0
12167 /*-----------------------------------------------------------------*/
12168 /* genFarFarAssign - assignment when both are in far space         */
12169 /*-----------------------------------------------------------------*/
12170 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12171 {
12172     int size = AOP_SIZE(right);
12173     int offset = 0;
12174     char *l ;
12175     /* first push the right side on to the stack */
12176     while (size--) {
12177         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12178         MOVA(l);
12179         pic16_emitcode ("push","acc");
12180     }
12181     
12182     pic16_freeAsmop(right,NULL,ic,FALSE);
12183     /* now assign DPTR to result */
12184     pic16_aopOp(result,ic,FALSE);
12185     size = AOP_SIZE(result);
12186     while (size--) {
12187         pic16_emitcode ("pop","acc");
12188         pic16_aopPut(AOP(result),"a",--offset);
12189     }
12190     pic16_freeAsmop(result,NULL,ic,FALSE);
12191         
12192 }
12193 #endif
12194
12195 /*-----------------------------------------------------------------*/
12196 /* genAssign - generate code for assignment                        */
12197 /*-----------------------------------------------------------------*/
12198 static void genAssign (iCode *ic)
12199 {
12200   operand *result, *right;
12201   int size, offset,know_W;
12202   unsigned long lit = 0L;
12203
12204   result = IC_RESULT(ic);
12205   right  = IC_RIGHT(ic) ;
12206
12207   FENTRY;
12208   
12209   /* if they are the same */
12210   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12211     return ;
12212
12213   /* reversed order operands are aopOp'ed so that result operand
12214    * is effective in case right is a stack symbol. This maneauver
12215    * allows to use the _G.resDirect flag later */
12216   pic16_aopOp(result,ic,TRUE);
12217   pic16_aopOp(right,ic,FALSE);
12218
12219   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12220
12221   /* if they are the same registers */
12222   if (pic16_sameRegs(AOP(right),AOP(result)))
12223     goto release;
12224
12225   /* if the result is a bit */
12226   if (AOP_TYPE(result) == AOP_CRY) {
12227     /* if the right size is a literal then
12228        we know what the value is */
12229     if (AOP_TYPE(right) == AOP_LIT) {
12230           
12231       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12232                   pic16_popGet(AOP(result),0));
12233
12234       if (((int) operandLitValue(right))) 
12235         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12236                        AOP(result)->aopu.aop_dir,
12237                        AOP(result)->aopu.aop_dir);
12238       else
12239         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12240                        AOP(result)->aopu.aop_dir,
12241                        AOP(result)->aopu.aop_dir);
12242       goto release;
12243     }
12244
12245     /* the right is also a bit variable */
12246     if (AOP_TYPE(right) == AOP_CRY) {
12247       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12248       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12249       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12250
12251       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12252                      AOP(result)->aopu.aop_dir,
12253                      AOP(result)->aopu.aop_dir);
12254       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12255                      AOP(right)->aopu.aop_dir,
12256                      AOP(right)->aopu.aop_dir);
12257       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12258                      AOP(result)->aopu.aop_dir,
12259                      AOP(result)->aopu.aop_dir);
12260       goto release ;
12261     }
12262
12263     /* we need to or */
12264     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12265     pic16_toBoolean(right);
12266     emitSKPZ;
12267     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12268     //pic16_aopPut(AOP(result),"a",0);
12269     goto release ;
12270   }
12271
12272   /* bit variables done */
12273   /* general case */
12274   size = AOP_SIZE(result);
12275   offset = 0 ;
12276
12277   if(AOP_TYPE(right) == AOP_LIT) {
12278         if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12279                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12280         else{
12281            union {
12282               unsigned long lit_int;
12283               float lit_float;
12284             } info;
12285         
12286
12287               if(IS_FIXED16X16(operandType(right))) {
12288                 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12289               } else {
12290                 /* take care if literal is a float */
12291                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12292                 lit = info.lit_int;
12293               }
12294         }
12295   }
12296
12297 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12298 //                      sizeof(unsigned long int), sizeof(float));
12299
12300
12301   if (AOP_TYPE(right) == AOP_REG) {
12302     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12303     while (size--) {
12304       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12305     } // while
12306     goto release;
12307   }
12308
12309   /* when do we have to read the program memory?
12310    * - if right itself is a symbol in code space
12311    *   (we don't care what it points to if it's a pointer)
12312    * - AND right is not a function (we would want its address)
12313    */
12314   if(AOP_TYPE(right) != AOP_LIT
12315         && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12316         && !IS_FUNC(OP_SYM_TYPE(right))
12317         && !IS_ITEMP(right))
12318   {
12319         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12320         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12321
12322         // set up table pointer
12323         if(is_LitOp(right)) {
12324 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12325                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12326                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12327                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12328                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12329                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12330                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12331         } else {
12332 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12333                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12334                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12335                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12336                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12337                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12338                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12339         }
12340
12341         /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12342         size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12343         while(size--) {
12344                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12345                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12346                         pic16_popGet(AOP(result),offset)));
12347                 offset++;
12348         }
12349
12350         /* FIXME: for pointers we need to extend differently (according
12351          * to pointer type DATA/CODE/EEPROM/... :*/
12352         size = getSize(OP_SYM_TYPE(right));
12353         if(AOP_SIZE(result) > size) {
12354                 size = AOP_SIZE(result) - size;
12355                 while(size--) {
12356                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12357                         offset++;
12358                 }
12359         }
12360         goto release;
12361   }
12362
12363
12364
12365 #if 0
12366 /* VR - What is this?! */
12367   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12368     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12369     if(aopIdx(AOP(result),0) == 4) {
12370
12371       /* this is a workaround to save value of right into wreg too,
12372        * value of wreg is going to be used later */
12373       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12374       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12375       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12376       goto release;
12377     } else
12378 //      assert(0);
12379       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12380   }
12381 #endif
12382
12383   know_W=-1;
12384   while (size--) {
12385   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12386     if(AOP_TYPE(right) == AOP_LIT) {
12387       if(lit&0xff) {
12388         if(know_W != (lit&0xff))
12389           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12390         know_W = lit&0xff;
12391         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12392       } else
12393         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12394
12395       lit >>= 8;
12396
12397     } else if (AOP_TYPE(right) == AOP_CRY) {
12398       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12399       if(offset == 0) {
12400         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12401         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12402         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12403       }
12404     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12405         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12406         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12407     } else {
12408       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12409
12410       if(!_G.resDirect)         /* use this aopForSym feature */
12411         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12412     }
12413             
12414     offset++;
12415   }
12416   
12417  release:
12418   pic16_freeAsmop (right,NULL,ic,FALSE);
12419   pic16_freeAsmop (result,NULL,ic,TRUE);
12420 }   
12421
12422 /*-----------------------------------------------------------------*/
12423 /* genJumpTab - generates code for jump table                       */
12424 /*-----------------------------------------------------------------*/
12425 static void genJumpTab (iCode *ic)
12426 {
12427   symbol *jtab;
12428   char *l;
12429   pCodeOp *jt_offs;
12430   pCodeOp *jt_offs_hi;
12431   pCodeOp *jt_label;
12432
12433     FENTRY;
12434
12435     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12436     /* get the condition into accumulator */
12437     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12438     MOVA(l);
12439     /* multiply by three */
12440     pic16_emitcode("add","a,acc");
12441     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12442
12443     jtab = newiTempLabel(NULL);
12444     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12445     pic16_emitcode("jmp","@a+dptr");
12446     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12447
12448 #if 0
12449     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12450     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12451     emitSKPNC;
12452     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12453     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12454     pic16_emitpLabel(jtab->key);
12455
12456 #else
12457
12458     jt_offs = pic16_popGetTempReg(0);
12459     jt_offs_hi = pic16_popGetTempReg(1);
12460     jt_label = pic16_popGetLabel (jtab->key);
12461     //fprintf (stderr, "Creating jump table...\n");
12462
12463     // calculate offset into jump table (idx * sizeof (GOTO))
12464     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12465     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12466     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12467     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12468     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12469     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12470     pic16_emitpcode(POC_MOVWF , jt_offs);
12471
12472     // prepare PCLATx (set to first entry in jump table)
12473     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12474     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12475     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12476     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12477     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12478
12479     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12480     pic16_emitpcode(POC_ADDWF , jt_offs);
12481     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12482     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12483     emitSKPNC;
12484     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12485
12486     // release temporaries and prepare jump into table (new PCL --> WREG)
12487     pic16_emitpcode(POC_MOVFW , jt_offs);
12488     pic16_popReleaseTempReg (jt_offs_hi, 1);
12489     pic16_popReleaseTempReg (jt_offs, 0);
12490
12491     // jump into the table
12492     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12493
12494     pic16_emitpLabelFORCE(jtab->key);
12495 #endif
12496
12497     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12498 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12499
12500     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12501     /* now generate the jump labels */
12502     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12503          jtab = setNextItem(IC_JTLABELS(ic))) {
12504 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12505         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12506         
12507     }
12508     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12509
12510 }
12511
12512 /*-----------------------------------------------------------------*/
12513 /* genMixedOperation - gen code for operators between mixed types  */
12514 /*-----------------------------------------------------------------*/
12515 /*
12516   TSD - Written for the PIC port - but this unfortunately is buggy.
12517   This routine is good in that it is able to efficiently promote 
12518   types to different (larger) sizes. Unfortunately, the temporary
12519   variables that are optimized out by this routine are sometimes
12520   used in other places. So until I know how to really parse the 
12521   iCode tree, I'm going to not be using this routine :(.
12522 */
12523 static int genMixedOperation (iCode *ic)
12524 {
12525 #if 0
12526   operand *result = IC_RESULT(ic);
12527   sym_link *ctype = operandType(IC_LEFT(ic));
12528   operand *right = IC_RIGHT(ic);
12529   int ret = 0;
12530   int big,small;
12531   int offset;
12532
12533   iCode *nextic;
12534   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12535
12536   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12537
12538   nextic = ic->next;
12539   if(!nextic)
12540     return 0;
12541
12542   nextright = IC_RIGHT(nextic);
12543   nextleft  = IC_LEFT(nextic);
12544   nextresult = IC_RESULT(nextic);
12545
12546   pic16_aopOp(right,ic,FALSE);
12547   pic16_aopOp(result,ic,FALSE);
12548   pic16_aopOp(nextright,  nextic, FALSE);
12549   pic16_aopOp(nextleft,   nextic, FALSE);
12550   pic16_aopOp(nextresult, nextic, FALSE);
12551
12552   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12553
12554     operand *t = right;
12555     right = nextright;
12556     nextright = t; 
12557
12558     pic16_emitcode(";remove right +","");
12559
12560   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12561 /*
12562     operand *t = right;
12563     right = nextleft;
12564     nextleft = t; 
12565 */
12566     pic16_emitcode(";remove left +","");
12567   } else
12568     return 0;
12569
12570   big = AOP_SIZE(nextleft);
12571   small = AOP_SIZE(nextright);
12572
12573   switch(nextic->op) {
12574
12575   case '+':
12576     pic16_emitcode(";optimize a +","");
12577     /* if unsigned or not an integral type */
12578     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12579       pic16_emitcode(";add a bit to something","");
12580     } else {
12581
12582       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12583
12584       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12585         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12586         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12587       } else
12588         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12589
12590       offset = 0;
12591       while(--big) {
12592
12593         offset++;
12594
12595         if(--small) {
12596           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12597             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12598             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12599           }
12600
12601           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12602           emitSKPNC;
12603           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12604                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12605                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12606           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12607           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12608
12609         } else {
12610           pic16_emitcode("rlf","known_zero,w");
12611
12612           /*
12613             if right is signed
12614               btfsc  right,7
12615                addlw ff
12616           */
12617           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12618             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12619             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12620           } else {
12621             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12622           }
12623         }
12624       }
12625       ret = 1;
12626     }
12627   }
12628   ret = 1;
12629
12630 release:
12631   pic16_freeAsmop(right,NULL,ic,TRUE);
12632   pic16_freeAsmop(result,NULL,ic,TRUE);
12633   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12634   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12635   if(ret)
12636     nextic->generated = 1;
12637
12638   return ret;
12639 #else
12640   return 0;
12641 #endif
12642 }
12643 /*-----------------------------------------------------------------*/
12644 /* genCast - gen code for casting                                  */
12645 /*-----------------------------------------------------------------*/
12646 static void genCast (iCode *ic)
12647 {
12648   operand *result = IC_RESULT(ic);
12649   sym_link *ctype = operandType(IC_LEFT(ic));
12650   sym_link *rtype = operandType(IC_RIGHT(ic));
12651   sym_link *restype = operandType(IC_RESULT(ic));
12652   operand *right = IC_RIGHT(ic);
12653   int size, offset ;
12654
12655
12656     FENTRY;
12657
12658         /* if they are equivalent then do nothing */
12659 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12660 //              return ;
12661
12662         pic16_aopOp(result,ic,FALSE);
12663         pic16_aopOp(right,ic,FALSE) ;
12664
12665         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12666
12667
12668         /* if the result is a bit */
12669         if (AOP_TYPE(result) == AOP_CRY) {
12670         
12671                 /* if the right size is a literal then
12672                  * we know what the value is */
12673                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12674
12675                 if (AOP_TYPE(right) == AOP_LIT) {
12676                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12677                                 pic16_popGet(AOP(result),0));
12678
12679                         if (((int) operandLitValue(right))) 
12680                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12681                                         AOP(result)->aopu.aop_dir,
12682                                         AOP(result)->aopu.aop_dir);
12683                         else
12684                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12685                                         AOP(result)->aopu.aop_dir,
12686                                         AOP(result)->aopu.aop_dir);
12687                         goto release;
12688                 }
12689
12690                 /* the right is also a bit variable */
12691                 if (AOP_TYPE(right) == AOP_CRY) {
12692                         emitCLRC;
12693                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12694
12695                         pic16_emitcode("clrc","");
12696                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12697                                 AOP(right)->aopu.aop_dir,
12698                                 AOP(right)->aopu.aop_dir);
12699                         pic16_aopPut(AOP(result),"c",0);
12700                         goto release ;
12701                 }
12702
12703                 /* we need to or */
12704                 if (AOP_TYPE(right) == AOP_REG) {
12705                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12706                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12707                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12708                 }
12709                 pic16_toBoolean(right);
12710                 pic16_aopPut(AOP(result),"a",0);
12711                 goto release ;
12712         }
12713
12714         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12715           int offset = 1;
12716
12717                 size = AOP_SIZE(result);
12718
12719                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12720
12721                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12722                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12723                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12724
12725                 while (size--)
12726                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12727
12728                 goto release;
12729         }
12730
12731         if(IS_BITFIELD(getSpec(restype))
12732           && IS_BITFIELD(getSpec(rtype))) {
12733           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12734         }
12735
12736         /* if they are the same size : or less */
12737         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12738
12739                 /* if they are in the same place */
12740                 if (pic16_sameRegs(AOP(right),AOP(result)))
12741                         goto release;
12742
12743                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12744 #if 0
12745                 if (IS_PTR_CONST(rtype))
12746 #else
12747                 if (IS_CODEPTR(rtype))
12748 #endif
12749                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12750
12751 #if 0
12752                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12753 #else
12754                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12755 #endif
12756                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12757
12758 #if 0
12759                 if(AOP_TYPE(right) == AOP_IMMD) {
12760                   pCodeOp *pcop0, *pcop1, *pcop2;
12761                   symbol *sym = OP_SYMBOL( right );
12762
12763                         size = AOP_SIZE(result);
12764                         /* low */
12765                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12766                         /* high */
12767                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12768                         /* upper */
12769                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12770         
12771                         if (size == 3) {
12772                                 pic16_emitpcode(POC_MOVLW, pcop0);
12773                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12774                                 pic16_emitpcode(POC_MOVLW, pcop1);
12775                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12776                                 pic16_emitpcode(POC_MOVLW, pcop2);
12777                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12778                         } else
12779                         if (size == 2) {
12780                                 pic16_emitpcode(POC_MOVLW, pcop0);
12781                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12782                                 pic16_emitpcode(POC_MOVLW, pcop1);
12783                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12784                         } else {
12785                                 pic16_emitpcode(POC_MOVLW, pcop0);
12786                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12787                         }
12788                 } else
12789 #endif
12790                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12791                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12792                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12793                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12794                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12795                         if(AOP_SIZE(result) <2)
12796                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12797                 } else {
12798                         /* if they in different places then copy */
12799                         size = AOP_SIZE(result);
12800                         offset = 0 ;
12801                         while (size--) {
12802                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12803                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12804                                 offset++;
12805                         }
12806                 }
12807                 goto release;
12808         }
12809
12810         /* if the result is of type pointer */
12811         if (IS_PTR(ctype)) {
12812           int p_type;
12813           sym_link *type = operandType(right);
12814           sym_link *etype = getSpec(type);
12815
12816                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
12817
12818                 /* pointer to generic pointer */
12819                 if (IS_GENPTR(ctype)) {
12820                   char *l = zero;
12821             
12822                         if (IS_PTR(type)) 
12823                                 p_type = DCL_TYPE(type);
12824                         else {
12825                 /* we have to go by the storage class */
12826                 p_type = PTR_TYPE(SPEC_OCLS(etype));
12827
12828 /*              if (SPEC_OCLS(etype)->codesp )  */
12829 /*                  p_type = CPOINTER ;  */
12830 /*              else */
12831 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12832 /*                      p_type = FPOINTER ; */
12833 /*                  else */
12834 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12835 /*                          p_type = PPOINTER; */
12836 /*                      else */
12837 /*                          if (SPEC_OCLS(etype) == idata ) */
12838 /*                              p_type = IPOINTER ; */
12839 /*                          else */
12840 /*                              p_type = POINTER ; */
12841             }
12842                 
12843             /* the first two bytes are known */
12844       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
12845             size = GPTRSIZE - 1; 
12846             offset = 0 ;
12847             while (size--) {
12848               if(offset < AOP_SIZE(right)) {
12849                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12850                 pic16_mov2f(AOP(result), AOP(right), offset);
12851 /*
12852                 if ((AOP_TYPE(right) == AOP_PCODE) && 
12853                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12854                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12855                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12856                 } else { 
12857                   
12858                   pic16_aopPut(AOP(result),
12859                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12860                          offset);
12861                 }
12862 */
12863               } else 
12864                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12865               offset++;
12866             }
12867             /* the last byte depending on type */
12868             switch (p_type) {
12869             case IPOINTER:
12870             case POINTER:
12871                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12872                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12873 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
12874                 break;
12875
12876             case CPOINTER:
12877                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12878                 break;
12879
12880             case FPOINTER:
12881               pic16_emitcode(";BUG!? ","%d",__LINE__);
12882                 l = one;
12883                 break;
12884             case PPOINTER:
12885               pic16_emitcode(";BUG!? ","%d",__LINE__);
12886                 l = "#0x03";
12887                 break;
12888
12889             case GPOINTER:
12890                 if (GPTRSIZE > AOP_SIZE(right)) {
12891                   // assume data pointer... THIS MIGHT BE WRONG!
12892                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12893                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12894                 } else {
12895                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12896                 }
12897               break;
12898               
12899             default:
12900                 /* this should never happen */
12901                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
12902                        "got unknown pointer type");
12903                 exit(1);
12904             }
12905             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
12906             goto release ;
12907         }
12908         
12909         
12910         assert( 0 );
12911         /* just copy the pointers */
12912         size = AOP_SIZE(result);
12913         offset = 0 ;
12914         while (size--) {
12915             pic16_aopPut(AOP(result),
12916                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12917                    offset);
12918             offset++;
12919         }
12920         goto release ;
12921     }
12922     
12923
12924
12925     /* so we now know that the size of destination is greater
12926     than the size of the source.
12927     Now, if the next iCode is an operator then we might be
12928     able to optimize the operation without performing a cast.
12929     */
12930     if(genMixedOperation(ic))
12931       goto release;
12932
12933     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12934     
12935     /* we move to result for the size of source */
12936     size = AOP_SIZE(right);
12937     offset = 0 ;
12938
12939     while (size--) {
12940       if(!_G.resDirect)
12941         pic16_mov2f(AOP(result), AOP(right), offset);
12942       offset++;
12943     }
12944
12945     /* now depending on the sign of the destination */
12946     size = AOP_SIZE(result) - AOP_SIZE(right);
12947     /* if unsigned or not an integral type */
12948     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
12949       while (size--)
12950         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12951     } else {
12952       /* we need to extend the sign :( */
12953
12954       if(size == 1) {
12955         /* Save one instruction of casting char to int */
12956         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
12957         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12958         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
12959       } else {
12960         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
12961
12962         if(offset)
12963           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12964         else
12965           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12966         
12967         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
12968
12969         while (size--)
12970           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
12971       }
12972     }
12973
12974 release:
12975     pic16_freeAsmop(right,NULL,ic,TRUE);
12976     pic16_freeAsmop(result,NULL,ic,TRUE);
12977
12978 }
12979
12980 /*-----------------------------------------------------------------*/
12981 /* genDjnz - generate decrement & jump if not zero instrucion      */
12982 /*-----------------------------------------------------------------*/
12983 static int genDjnz (iCode *ic, iCode *ifx)
12984 {
12985     symbol *lbl, *lbl1;
12986     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12987
12988     if (!ifx)
12989         return 0;
12990     
12991     /* if the if condition has a false label
12992        then we cannot save */
12993     if (IC_FALSE(ifx))
12994         return 0;
12995
12996     /* if the minus is not of the form 
12997        a = a - 1 */
12998     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
12999         !IS_OP_LITERAL(IC_RIGHT(ic)))
13000         return 0;
13001
13002     if (operandLitValue(IC_RIGHT(ic)) != 1)
13003         return 0;
13004
13005     /* if the size of this greater than one then no
13006        saving */
13007     if (getSize(operandType(IC_RESULT(ic))) > 1)
13008         return 0;
13009
13010     /* otherwise we can save BIG */
13011     lbl = newiTempLabel(NULL);
13012     lbl1= newiTempLabel(NULL);
13013
13014     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13015     
13016     if (IS_AOP_PREG(IC_RESULT(ic))) {
13017         pic16_emitcode("dec","%s",
13018                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13019         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13020         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13021     } else {    
13022
13023
13024       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13025       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13026
13027       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13028       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13029
13030     }
13031     
13032     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13033     ifx->generated = 1;
13034     return 1;
13035 }
13036
13037 /*-----------------------------------------------------------------*/
13038 /* genReceive - generate code for a receive iCode                  */
13039 /*-----------------------------------------------------------------*/
13040 static void genReceive (iCode *ic)
13041 {    
13042
13043   FENTRY;
13044
13045 #if 0
13046   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13047         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13048 #endif
13049 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13050
13051   if (isOperandInFarSpace(IC_RESULT(ic))
13052       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13053           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13054
13055     int size = getSize(operandType(IC_RESULT(ic)));
13056     int offset =  pic16_fReturnSizePic - size;
13057
13058       assert( 0 );
13059       while (size--) {
13060         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13061                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13062                       offset++;
13063         }
13064
13065       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13066
13067       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13068       size = AOP_SIZE(IC_RESULT(ic));
13069       offset = 0;
13070       while (size--) {
13071         pic16_emitcode ("pop","acc");
13072         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13073       }
13074   } else {
13075     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13076     _G.accInUse++;
13077     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13078     _G.accInUse--;
13079
13080     /* set pseudo stack pointer to where it should be - dw*/
13081     GpsuedoStkPtr = ic->parmBytes;
13082
13083     /* setting GpsuedoStkPtr has side effects here: */
13084     assignResultValue(IC_RESULT(ic), 0);
13085   }
13086
13087   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13088 }
13089
13090 /*-----------------------------------------------------------------*/
13091 /* genDummyRead - generate code for dummy read of volatiles        */
13092 /*-----------------------------------------------------------------*/
13093 static void
13094 genDummyRead (iCode * ic)
13095 {
13096   operand *op;
13097   int i;
13098
13099   op = IC_RIGHT(ic);
13100   if (op && IS_SYMOP(op)) {
13101     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13102       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13103       return;
13104     }
13105     pic16_aopOp (op, ic, FALSE);
13106     for (i=0; i < AOP_SIZE(op); i++) {
13107       // may need to protect this from the peepholer -- this is not nice but works...
13108       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13109       pic16_mov2w (AOP(op),i);
13110       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13111     } // for i
13112     pic16_freeAsmop (op, NULL, ic, TRUE);
13113   } else if (op) {
13114     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13115   } // if
13116 }
13117
13118 /*-----------------------------------------------------------------*/
13119 /* genpic16Code - generate code for pic16 based controllers        */
13120 /*-----------------------------------------------------------------*/
13121 /*
13122  * At this point, ralloc.c has gone through the iCode and attempted
13123  * to optimize in a way suitable for a PIC. Now we've got to generate
13124  * PIC instructions that correspond to the iCode.
13125  *
13126  * Once the instructions are generated, we'll pass through both the
13127  * peep hole optimizer and the pCode optimizer.
13128  *-----------------------------------------------------------------*/
13129
13130 void genpic16Code (iCode *lic)
13131 {
13132   iCode *ic;
13133   int cln = 0;
13134
13135     lineHead = lineCurr = NULL;
13136
13137     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13138     pic16_addpBlock(pb);
13139
13140 #if 0
13141     /* if debug information required */
13142     if (options.debug && currFunc) {
13143       if (currFunc) {
13144         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13145       }
13146     }
13147 #endif
13148
13149     for (ic = lic ; ic ; ic = ic->next ) {
13150
13151       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13152       if ( cln != ic->lineno ) {
13153         if ( options.debug ) {
13154           debugFile->writeCLine (ic);
13155         }
13156         
13157         if(!options.noCcodeInAsm) {
13158           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13159               printCLine(ic->filename, ic->lineno)));
13160         }
13161
13162         cln = ic->lineno ;
13163       }
13164         
13165       if(options.iCodeInAsm) {
13166         char *l;
13167
13168           /* insert here code to print iCode as comment */
13169           l = Safe_strdup(printILine(ic));
13170           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13171       }
13172         
13173       /* if the result is marked as
13174        * spilt and rematerializable or code for
13175        * this has already been generated then
13176        * do nothing */
13177       if (resultRemat(ic) || ic->generated ) 
13178         continue ;
13179         
13180       /* depending on the operation */
13181       switch (ic->op) {
13182         case '!' :
13183           pic16_genNot(ic);
13184           break;
13185             
13186         case '~' :
13187           pic16_genCpl(ic);
13188           break;
13189             
13190         case UNARYMINUS:
13191           genUminus (ic);
13192           break;
13193             
13194         case IPUSH:
13195           genIpush (ic);
13196           break;
13197             
13198         case IPOP:
13199           /* IPOP happens only when trying to restore a 
13200            * spilt live range, if there is an ifx statement
13201            * following this pop then the if statement might
13202            * be using some of the registers being popped which
13203            * would destroy the contents of the register so
13204            * we need to check for this condition and handle it */
13205            if (ic->next
13206              && ic->next->op == IFX
13207              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13208                genIfx (ic->next,ic);
13209           else
13210             genIpop (ic);
13211           break; 
13212             
13213         case CALL:
13214           genCall (ic);
13215           break;
13216             
13217         case PCALL:
13218           genPcall (ic);
13219           break;
13220             
13221         case FUNCTION:
13222           genFunction (ic);
13223           break;
13224             
13225         case ENDFUNCTION:
13226           genEndFunction (ic);
13227           break;
13228             
13229         case RETURN:
13230           genRet (ic);
13231           break;
13232             
13233         case LABEL:
13234           genLabel (ic);
13235           break;
13236             
13237         case GOTO:
13238           genGoto (ic);
13239           break;
13240             
13241         case '+' :
13242           pic16_genPlus (ic) ;
13243           break;
13244             
13245         case '-' :
13246           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13247             pic16_genMinus (ic);
13248           break;
13249
13250         case '*' :
13251           genMult (ic);
13252           break;
13253             
13254         case '/' :
13255           genDiv (ic) ;
13256           break;
13257             
13258         case '%' :
13259           genMod (ic);
13260           break;
13261             
13262         case '>' :
13263           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13264           break;
13265             
13266         case '<' :
13267           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13268           break;
13269             
13270         case LE_OP:
13271         case GE_OP:
13272         case NE_OP:
13273           /* note these two are xlated by algebraic equivalence
13274            * during parsing SDCC.y */
13275           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13276             "got '>=' or '<=' shouldn't have come here");
13277           break;
13278
13279         case EQ_OP:
13280           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13281           break;            
13282             
13283         case AND_OP:
13284           genAndOp (ic);
13285           break;
13286             
13287         case OR_OP:
13288           genOrOp (ic);
13289           break;
13290             
13291         case '^' :
13292           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13293           break;
13294             
13295         case '|' :
13296           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13297           break;
13298             
13299         case BITWISEAND:
13300           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13301           break;
13302             
13303         case INLINEASM:
13304           genInline (ic);
13305           break;
13306             
13307         case RRC:
13308           genRRC (ic);
13309           break;
13310             
13311         case RLC:
13312           genRLC (ic);
13313           break;
13314             
13315         case GETHBIT:
13316           genGetHbit (ic);
13317           break;
13318             
13319         case LEFT_OP:
13320           genLeftShift (ic);
13321           break;
13322             
13323         case RIGHT_OP:
13324           genRightShift (ic);
13325           break;
13326             
13327         case GET_VALUE_AT_ADDRESS:
13328           genPointerGet(ic);
13329           break;
13330             
13331         case '=' :
13332           if (POINTER_SET(ic))
13333             genPointerSet(ic);
13334           else
13335             genAssign(ic);
13336           break;
13337             
13338         case IFX:
13339           genIfx (ic,NULL);
13340           break;
13341             
13342         case ADDRESS_OF:
13343           genAddrOf (ic);
13344           break;
13345             
13346         case JUMPTABLE:
13347           genJumpTab (ic);
13348           break;
13349             
13350         case CAST:
13351           genCast (ic);
13352           break;
13353             
13354         case RECEIVE:
13355           genReceive(ic);
13356           break;
13357             
13358         case SEND:
13359           addSet(&_G.sendSet,ic);
13360           break;
13361
13362         case DUMMY_READ_VOLATILE:
13363           genDummyRead (ic);
13364           break;
13365
13366         default :
13367           ic = ic;
13368       }
13369     }
13370
13371
13372     /* now we are ready to call the
13373        peep hole optimizer */
13374     if (!options.nopeep)
13375       peepHole (&lineHead);
13376
13377     /* now do the actual printing */
13378     printLine (lineHead, codeOutFile);
13379
13380 #ifdef PCODE_DEBUG
13381     DFPRINTF((stderr,"printing pBlock\n\n"));
13382     pic16_printpBlock(stdout,pb);
13383 #endif
13384
13385     return;
13386 }
13387