6d6e8bd669bb16b4cb2dfc2b47d77e2bae6c0b32
[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)
10   
11   This program is free software; you can redistribute it and/or modify it
12   under the terms of the GNU General Public License as published by the
13   Free Software Foundation; either version 2, or (at your option) any
14   later version.
15   
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   GNU General Public License for more details.
20   
21   You should have received a copy of the GNU General Public License
22   along with this program; if not, write to the Free Software
23   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24   
25   In other words, you are welcome to use, share and improve this program.
26   You are forbidden to forbid anyone else to use, share and improve
27   what you give them.   Help stamp out software-hoarding!
28   
29   Notes:
30   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
31                 Made everything static
32 -------------------------------------------------------------------------*/
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include "SDCCglobl.h"
39 #include "newalloc.h"
40
41 #include "common.h"
42 #include "SDCCpeeph.h"
43 #include "ralloc.h"
44 #include "pcode.h"
45 #include "gen.h"
46 #include "genutils.h"
47 #include "device.h"
48 #include "main.h"
49
50 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
51 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
52 void pic16_genMult8X8_8 (operand *, operand *,operand *);
53 void pic16_genMult16X16_16(operand *, operand *, operand *);
54 void pic16_genMult32X32_32(operand *, operand *, operand *);
55 pCode *pic16_AssembleLine(char *line, int peeps);
56 extern void pic16_printpBlock(FILE *of, pBlock *pb);
57 static asmop *newAsmop (short type);
58 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
59 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
60 static void mov2w (asmop *aop, int offset);
61 static int aopIdx (asmop *aop, int offset);
62
63 int pic16_labelOffset=0;
64 extern int pic16_debug_verbose;
65 static int optimized_for_speed = 0;
66 /*
67   hack hack
68
69 */
70
71 /* max_key keeps track of the largest label number used in 
72    a function. This is then used to adjust the label offset
73    for the next function.
74 */
75 static int max_key=0;
76 static int GpsuedoStkPtr=0;
77
78 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
79 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst);
80
81 unsigned int pic16aopLiteral (value *val, int offset);
82 const char *pic16_AopType(short type);
83 static iCode *ifxForOp ( operand *op, iCode *ic );
84
85 void pic16_pushpCodeOp(pCodeOp *pcop);
86 void pic16_poppCodeOp(pCodeOp *pcop);
87
88 static bool is_LitOp(operand *op);
89 static bool is_LitAOp(asmop *aop);
90
91
92 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
93
94 /* this is the down and dirty file with all kinds of 
95    kludgy & hacky stuff. This is what it is all about
96    CODE GENERATION for a specific MCU . some of the
97    routines may be reusable, will have to see */
98
99 static char *zero = "#0x00";
100 static char *one  = "#0x01";
101 static char *spname = "sp";
102
103
104 /*
105  * Function return value policy (MSB-->LSB):
106  *  8 bits      -> WREG
107  * 16 bits      -> PRODL:WREG
108  * 24 bits      -> PRODH:PRODL:WREG
109  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
110  * >32 bits     -> on stack, and FSR0 points to the beginning
111  *
112  */
113  
114
115 char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
116 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
117 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
118 static char **fReturn = fReturnpic16;
119
120 static char *accUse[] = {"WREG"};
121
122 //static short rbank = -1;
123
124 static struct {
125     short r0Pushed;
126     short r1Pushed;
127     short fsr0Pushed;
128     short accInUse;
129     short inLine;
130     short debugLine;
131     short nRegsSaved;
132     short ipushRegs;
133     set *sendSet;
134     int interruptvector;
135     int usefastretfie;
136 } _G;
137
138 /* Resolved ifx structure. This structure stores information
139    about an iCode ifx that makes it easier to generate code.
140 */
141 typedef struct resolvedIfx {
142   symbol *lbl;     /* pointer to a label */
143   int condition;   /* true or false ifx */
144   int generated;   /* set true when the code associated with the ifx
145                     * is generated */
146 } resolvedIfx;
147
148 extern int pic16_ptrRegReq ;
149 extern int pic16_nRegs;
150 extern FILE *codeOutFile;
151 static void saverbank (int, iCode *,bool);
152
153 static lineNode *lineHead = NULL;
154 static lineNode *lineCurr = NULL;
155
156 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
157 0xE0, 0xC0, 0x80, 0x00};
158 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
159 0x07, 0x03, 0x01, 0x00};
160
161 static  pBlock *pb;
162
163 /*-----------------------------------------------------------------*/
164 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
165 /*                 exponent of 2 is returned, otherwise -1 is      */
166 /*                 returned.                                       */
167 /* note that this is similar to the function `powof2' in SDCCsymt  */
168 /* if(n == 2^y)                                                    */
169 /*   return y;                                                     */
170 /* return -1;                                                      */
171 /*-----------------------------------------------------------------*/
172 static int my_powof2 (unsigned long num)
173 {
174   if(num) {
175     if( (num & (num-1)) == 0) {
176       int nshifts = -1;
177       while(num) {
178         num>>=1;
179         nshifts++;
180       }
181       return nshifts;
182     }
183   }
184
185   return -1;
186 }
187
188 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
189 {
190   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
191                        line_no,
192                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
193                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
194                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
195                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
196                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
197                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
198                        ((result) ? AOP_SIZE(result) : 0));
199 }
200
201 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
202 {
203
204   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
205                        line_no,
206                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
207                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
208                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
209                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
210                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
211                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
212
213 }
214
215 void pic16_emitpcomment (char *fmt, ...)
216 {
217     va_list ap;
218     char lb[INITIAL_INLINEASM];  
219     char *lbp = lb;
220
221     va_start(ap,fmt);   
222
223     lb[0] = ';';
224     vsprintf(lb+1,fmt,ap);
225
226     while (isspace(*lbp)) lbp++;
227
228     if (lbp && *lbp) 
229         lineCurr = (lineCurr ?
230                     connectLine(lineCurr,newLineNode(lb)) :
231                     (lineHead = newLineNode(lb)));
232     lineCurr->isInline = _G.inLine;
233     lineCurr->isDebug  = _G.debugLine;
234
235     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
236     va_end(ap);
237
238 //      fprintf(stderr, "%s\n", lb);
239 }
240
241 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
242 {
243     va_list ap;
244     char lb[INITIAL_INLINEASM];  
245     char *lbp = lb;
246
247     if(!pic16_debug_verbose)
248       return;
249
250     va_start(ap,fmt);   
251
252     if (inst && *inst) {
253         if (fmt && *fmt)
254             sprintf(lb,"%s\t",inst);
255         else
256             sprintf(lb,"%s",inst);
257         vsprintf(lb+(strlen(lb)),fmt,ap);
258     }  else
259         vsprintf(lb,fmt,ap);
260
261     while (isspace(*lbp)) lbp++;
262
263     if (lbp && *lbp) 
264         lineCurr = (lineCurr ?
265                     connectLine(lineCurr,newLineNode(lb)) :
266                     (lineHead = newLineNode(lb)));
267     lineCurr->isInline = _G.inLine;
268     lineCurr->isDebug  = _G.debugLine;
269
270     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
271     va_end(ap);
272
273 //      fprintf(stderr, "%s\n", lb);
274 }
275
276 void pic16_emitpLabel(int key)
277 {
278   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
279 }
280
281 void pic16_emitpLabelFORCE(int key)
282 {
283   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
284 }
285
286 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
287 {
288
289   if(pcop)
290     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
291   else
292     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
293     
294 //    fprintf(stderr, "%s\n", pcop->name);
295 }
296
297 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
298 {
299
300   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
301
302 }
303
304
305 #if 1
306 #define pic16_emitcode  DEBUGpic16_emitcode
307 #else
308 /*-----------------------------------------------------------------*/
309 /* pic16_emitcode - writes the code into a file : for now it is simple    */
310 /*-----------------------------------------------------------------*/
311 void pic16_emitcode (char *inst,char *fmt, ...)
312 {
313     va_list ap;
314     char lb[INITIAL_INLINEASM];  
315     char *lbp = lb;
316
317     va_start(ap,fmt);   
318
319     if (inst && *inst) {
320         if (fmt && *fmt)
321             sprintf(lb,"%s\t",inst);
322         else
323             sprintf(lb,"%s",inst);
324         vsprintf(lb+(strlen(lb)),fmt,ap);
325     }  else
326         vsprintf(lb,fmt,ap);
327
328     while (isspace(*lbp)) lbp++;
329
330     if (lbp && *lbp) 
331         lineCurr = (lineCurr ?
332                     connectLine(lineCurr,newLineNode(lb)) :
333                     (lineHead = newLineNode(lb)));
334     lineCurr->isInline = _G.inLine;
335     lineCurr->isDebug  = _G.debugLine;
336
337 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
338
339 //    if(pic16_debug_verbose)
340 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
341
342     va_end(ap);
343 }
344 #endif
345
346
347 /*-----------------------------------------------------------------*/
348 /* pic16_emitDebuggerSymbol - associate the current code location  */
349 /*   with a debugger symbol                                        */
350 /*-----------------------------------------------------------------*/
351 void
352 pic16_emitDebuggerSymbol (char * debugSym)
353 {
354   _G.debugLine = 1;
355   pic16_emitcode (";", "%s ==.", debugSym);
356   _G.debugLine = 0;
357 }
358
359
360 /*-----------------------------------------------------------------*/
361 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
362 /*-----------------------------------------------------------------*/
363 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
364 {
365 //    bool r0iu = FALSE , r1iu = FALSE;
366 //    bool r0ou = FALSE , r1ou = FALSE;
367     bool fsr0iu = FALSE, fsr0ou;
368     bool fsr2iu = FALSE, fsr2ou;
369     
370     fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
371
372     
373     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
374     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
375     
376     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
377     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
378
379     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
380         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
381         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
382     }
383
384     /* no usage of FSR2 */
385     if(!fsr2iu && !fsr2ou) {
386         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
387         (*aopp)->type = AOP_FSR2;
388
389       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
390     }
391         
392     if(!fsr0iu && !fsr0ou) {
393         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
394         (*aopp)->type = AOP_FSR0;
395         
396       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
397     }
398
399     /* now we know they both have usage */
400     /* if fsr0 not used in this instruction */
401     if (!fsr0iu) {
402         if (!_G.fsr0Pushed) {
403                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
404                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
405                 _G.fsr0Pushed++;
406         }
407
408         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
409         (*aopp)->type = AOP_FSR0;
410
411       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
412     }
413         
414
415     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
416     assert( 0 );
417
418     return NULL;
419 #if 0
420     /* the logic: if r0 & r1 used in the instruction
421     then we are in trouble otherwise */
422
423     /* first check if r0 & r1 are used by this
424     instruction, in which case we are in trouble */
425     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
426         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
427     {
428         goto endOfWorld;      
429     }
430
431     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
432     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
433
434     /* if no usage of r0 then return it */
435     if (!r0iu && !r0ou) {
436         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
437         (*aopp)->type = AOP_R0;
438         
439         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
440     }
441
442     /* if no usage of r1 then return it */
443     if (!r1iu && !r1ou) {
444         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
445         (*aopp)->type = AOP_R1;
446
447         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
448     }    
449
450     /* now we know they both have usage */
451     /* if r0 not used in this instruction */
452     if (!r0iu) {
453         /* push it if not already pushed */
454         if (!_G.r0Pushed) {
455           //pic16_emitcode ("push","%s",
456           //          pic16_regWithIdx(R0_IDX)->dname);
457             _G.r0Pushed++ ;
458         }
459         
460         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
461         (*aopp)->type = AOP_R0;
462
463         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
464     }
465
466     /* if r1 not used then */
467
468     if (!r1iu) {
469         /* push it if not already pushed */
470         if (!_G.r1Pushed) {
471           //pic16_emitcode ("push","%s",
472           //          pic16_regWithIdx(R1_IDX)->dname);
473             _G.r1Pushed++ ;
474         }
475         
476         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
477         (*aopp)->type = AOP_R1;
478         return pic16_regWithIdx(R1_IDX);
479     }
480
481 endOfWorld :
482     /* I said end of world but not quite end of world yet */
483     /* if this is a result then we can push it on the stack*/
484     if (result) {
485         (*aopp)->type = AOP_STK;    
486         return NULL;
487     }
488
489     /* other wise this is true end of the world */
490     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
491            "getFreePtr should never reach here");
492     exit(0);
493 #endif
494 }
495
496 /*-----------------------------------------------------------------*/
497 /* newAsmop - creates a new asmOp                                  */
498 /*-----------------------------------------------------------------*/
499 static asmop *newAsmop (short type)
500 {
501     asmop *aop;
502
503     aop = Safe_calloc(1,sizeof(asmop));
504     aop->type = type;
505     return aop;
506 }
507
508 static void genSetDPTR(int n)
509 {
510     if (!n)
511     {
512         pic16_emitcode(";", "Select standard DPTR");
513         pic16_emitcode("mov", "dps, #0x00");
514     }
515     else
516     {
517         pic16_emitcode(";", "Select alternate DPTR");
518         pic16_emitcode("mov", "dps, #0x01");
519     }
520 }
521
522 /*-----------------------------------------------------------------*/
523 /* resolveIfx - converts an iCode ifx into a form more useful for  */
524 /*              generating code                                    */
525 /*-----------------------------------------------------------------*/
526 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
527 {
528
529   DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
530
531   if(!resIfx) 
532     return;
533
534
535   resIfx->condition = 1;    /* assume that the ifx is true */
536   resIfx->generated = 0;    /* indicate that the ifx has not been used */
537
538   if(!ifx) {
539     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
540
541 #if 1
542     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
543                         __FUNCTION__,__LINE__,resIfx->lbl->key);
544 #endif
545
546   } else {
547     if(IC_TRUE(ifx)) {
548       resIfx->lbl = IC_TRUE(ifx);
549     } else {
550       resIfx->lbl = IC_FALSE(ifx);
551       resIfx->condition = 0;
552     }
553
554 #if 1
555     if(IC_TRUE(ifx)) 
556       DEBUGpic16_emitcode("; ***","ifx true is non-null");
557     if(IC_FALSE(ifx)) 
558       DEBUGpic16_emitcode("; ***","ifx false is non-null");
559 #endif
560   }
561
562   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
563
564 }
565 #if 0
566 /*-----------------------------------------------------------------*/
567 /* pointerCode - returns the code for a pointer type               */
568 /*-----------------------------------------------------------------*/
569 static int pointerCode (sym_link *etype)
570 {
571
572     return PTR_TYPE(SPEC_OCLS(etype));
573
574 }
575 #endif
576
577 /*-----------------------------------------------------------------*/
578 /* aopForSym - for a true symbol                                   */
579 /*-----------------------------------------------------------------*/
580 static asmop *aopForSym (iCode *ic, operand *op, bool result)
581 {
582     symbol *sym=OP_SYMBOL(op);
583     asmop *aop;
584     memmap *space= SPEC_OCLS(sym->etype);
585
586     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
587
588 //    sym = OP_SYMBOL(op);
589
590     /* if already has one */
591     if (sym->aop) {
592             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
593         return sym->aop;
594     }
595
596     /* if symbol was initially placed onStack then we must re-place it
597      * to direct memory, since pic16 does not have a specific stack */
598     if(sym->onStack) {
599         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
600     }
601
602
603 #if 1
604     /* assign depending on the storage class */
605     /* if it is on the stack or indirectly addressable */
606     /* space we need to assign either r0 or r1 to it   */    
607     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
608
609         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
610                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
611         
612         sym->aop = aop = newAsmop(0);
613         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
614         aop->size = getSize(sym->type);
615
616         fprintf(stderr, "%s:%d\t%s\n", __FILE__, __LINE__, __FUNCTION__);
617
618 #if 1
619 //        sym->aop = aop = newAsmop (AOP_REG);
620 //        aop->aopu.aop_dir = sym->name;        //sym->rname ;
621 //      aop->aopu.aop_reg[0] = pic16_regWithIdx(IDX_PLUSW0);    //pic16_pc_plusw2.r;
622 //        aop->size = getSize(sym->type);
623         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
624         
625 //      if(_G.accInUse) {
626 //              pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
627 //      }
628         
629 //      pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popCopyReg(&pic16_pc_fsr2l), pic16_popCopyReg(&pic16_pc_fsr0l)));
630 //      pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popCopyReg(&pic16_pc_fsr2h), pic16_popCopyReg(&pic16_pc_fsr0h)));
631         
632         
633         /* initialise for stack access via frame pointer */
634         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
635
636 //      pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
637 //              pic16_popCopyReg(&pic16_pc_plusw2), pic16_popCopyReg(&pic16_pc_kzero)));
638         
639 //      if(_G.accInUse) {
640 //              pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
641 //      }
642         
643         return (aop);
644 #endif
645
646 #if 0
647         /* now assign the address of the variable to 
648         the pointer register */
649         if (aop->type != AOP_STK) {
650
651             if (sym->onStack) {
652                     if ( _G.accInUse )
653                         pic16_emitcode("push","acc");
654
655                     pic16_emitcode("mov","a,_bp");
656                     pic16_emitcode("add","a,#0x%02x",
657                              ((sym->stack < 0) ?
658                               ((char)(sym->stack - _G.nRegsSaved )) :
659                               ((char)sym->stack)) & 0xff);
660                     pic16_emitcode("mov","%s,a",
661                              aop->aopu.aop_ptr->name);
662
663                     if ( _G.accInUse )
664                         pic16_emitcode("pop","acc");
665             } else
666                 pic16_emitcode("mov","%s,#%s",
667                          aop->aopu.aop_ptr->name,
668                          sym->rname);
669             aop->paged = space->paged;
670         } else
671             aop->aopu.aop_stk = sym->stack;
672         return aop;
673 #endif
674
675     }
676 #endif
677
678 #if 0
679     if (sym->onStack && options.stack10bit)
680     {
681         /* It's on the 10 bit stack, which is located in
682          * far data space.
683          */
684          
685       //DEBUGpic16_emitcode(";","%d",__LINE__);
686
687         if ( _G.accInUse )
688                 pic16_emitcode("push","acc");
689
690         pic16_emitcode("mov","a,_bp");
691         pic16_emitcode("add","a,#0x%02x",
692                  ((sym->stack < 0) ?
693                    ((char)(sym->stack - _G.nRegsSaved )) :
694                    ((char)sym->stack)) & 0xff);
695         
696         genSetDPTR(1);
697         pic16_emitcode ("mov","dpx1,#0x40");
698         pic16_emitcode ("mov","dph1,#0x00");
699         pic16_emitcode ("mov","dpl1, a");
700         genSetDPTR(0);
701         
702         if ( _G.accInUse )
703             pic16_emitcode("pop","acc");
704             
705         sym->aop = aop = newAsmop(AOP_DPTR2);
706         aop->size = getSize(sym->type); 
707         return aop;
708     }
709 #endif
710     //DEBUGpic16_emitcode(";","%d",__LINE__);
711     /* if in bit space */
712     if (IN_BITSPACE(space)) {
713         sym->aop = aop = newAsmop (AOP_CRY);
714         aop->aopu.aop_dir = sym->rname ;
715         aop->size = getSize(sym->type);
716         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
717         return aop;
718     }
719     /* if it is in direct space */
720     if (IN_DIRSPACE(space)) {
721         sym->aop = aop = newAsmop (AOP_DIR);
722         aop->aopu.aop_dir = sym->rname ;
723         aop->size = getSize(sym->type);
724         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
725         pic16_allocDirReg( IC_LEFT(ic) );
726         return aop;
727     }
728
729     if (IN_FARSPACE(space)) {
730         sym->aop = aop = newAsmop (AOP_DIR);
731         aop->aopu.aop_dir = sym->rname ;
732         aop->size = getSize(sym->type);
733         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
734         pic16_allocDirReg( IC_LEFT(ic) );
735         return aop;
736     }
737
738 #if 0                                                                                           // patch 14
739     /* special case for a function */
740     if (IS_FUNC(sym->type)) {   
741         sym->aop = aop = newAsmop(AOP_IMMD);    
742         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
743         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
744         strcpy(aop->aopu.aop_immd,sym->rname);
745         aop->size = FPTRSIZE; 
746         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
747         return aop;
748     }
749 #endif                                                                                          // patch 14
750
751
752     /* only remaining is far space */
753     /* in which case DPTR gets the address */
754     sym->aop = aop = newAsmop(AOP_PCODE);
755
756 /* change the next if to 1 to revert to good old immediate code */
757         if(IN_CODESPACE(space)) {
758                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
759                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
760                 PCOI(aop->aopu.pcop)->index = 0;
761         } else {
762                 /* try to allocate via direct register */
763                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
764 //              aop->size = getSize( sym->type );
765         }
766
767         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
768                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
769
770 #if 0
771         if(!pic16_allocDirReg (IC_LEFT(ic)))
772                 return NULL;
773 #endif
774
775         if(IN_DIRSPACE( space ))
776                 aop->size = PTRSIZE;
777         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
778                 aop->size = FPTRSIZE;
779         else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
780         else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
781         else {
782                 assert( 0 );
783         }
784
785     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
786
787     /* if it is in code space */
788     if (IN_CODESPACE(space))
789         aop->code = 1;
790
791     return aop;     
792 }
793
794 /*-----------------------------------------------------------------*/
795 /* aopForRemat - rematerialzes an object                           */
796 /*-----------------------------------------------------------------*/
797 static asmop *aopForRemat (operand *op) // x symbol *sym)
798 {
799   symbol *sym = OP_SYMBOL(op);
800   iCode *ic = NULL, *oldic;
801   asmop *aop = newAsmop(AOP_PCODE);
802   int val = 0;
803   int offset = 0;
804   int viaimmd=0;
805
806
807         ic = sym->rematiCode;
808
809         DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
810         
811         if(IS_OP_POINTER(op)) {
812                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
813         }
814
815         for (;;) {
816                 oldic = ic;
817
818 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
819         
820                 if (ic->op == '+') {
821                         val += (int) operandLitValue(IC_RIGHT(ic));
822                 } else if (ic->op == '-') {
823                         val -= (int) operandLitValue(IC_RIGHT(ic));
824                 } else
825                         break;
826                 
827                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
828         }
829
830         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
831
832         if(!op->isaddr)viaimmd++; else viaimmd=0;
833                 
834 /* set the following if to 1 to revert to good old immediate code */
835         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
836                 || viaimmd) {
837
838                 DEBUGpic16_emitcode("%s:%d immediate", __FILE__, __LINE__);
839
840                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
841
842 #if 0
843                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
844 #else
845                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
846 #endif
847
848                 PCOI(aop->aopu.pcop)->index = val;
849         } else {
850                 DEBUGpic16_emitcode("%s:%d dir", __FILE__, __LINE__);
851
852                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
853                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
854 //              aop->size = AOP_SIZE( IC_LEFT(ic) );
855         }
856
857
858         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
859                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
860 #if 0
861                 val, IS_PTR_CONST(operandType(op)));
862 #else
863                 val, IS_CODEPTR(operandType(op)));
864 #endif
865
866 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
867
868         pic16_allocDirReg (IC_LEFT(ic));
869
870         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
871                 aop->code = 1;
872
873   return aop;        
874 }
875
876 static int aopIdx (asmop *aop, int offset)
877 {
878   if(!aop)
879     return -1;
880
881   if(aop->type !=  AOP_REG)
882     return -2;
883         
884   return aop->aopu.aop_reg[offset]->rIdx;
885
886 }
887 /*-----------------------------------------------------------------*/
888 /* regsInCommon - two operands have some registers in common       */
889 /*-----------------------------------------------------------------*/
890 static bool regsInCommon (operand *op1, operand *op2)
891 {
892     symbol *sym1, *sym2;
893     int i;
894
895     /* if they have registers in common */
896     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
897         return FALSE ;
898
899     sym1 = OP_SYMBOL(op1);
900     sym2 = OP_SYMBOL(op2);
901
902     if (sym1->nRegs == 0 || sym2->nRegs == 0)
903         return FALSE ;
904
905     for (i = 0 ; i < sym1->nRegs ; i++) {
906         int j;
907         if (!sym1->regs[i])
908             continue ;
909
910         for (j = 0 ; j < sym2->nRegs ;j++ ) {
911             if (!sym2->regs[j])
912                 continue ;
913
914             if (sym2->regs[j] == sym1->regs[i])
915                 return TRUE ;
916         }
917     }
918
919     return FALSE ;
920 }
921
922 /*-----------------------------------------------------------------*/
923 /* operandsEqu - equivalent                                        */
924 /*-----------------------------------------------------------------*/
925 static bool operandsEqu ( operand *op1, operand *op2)
926 {
927     symbol *sym1, *sym2;
928
929     /* if they not symbols */
930     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
931         return FALSE;
932
933     sym1 = OP_SYMBOL(op1);
934     sym2 = OP_SYMBOL(op2);
935
936     /* if both are itemps & one is spilt
937        and the other is not then false */
938     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
939         sym1->isspilt != sym2->isspilt )
940         return FALSE ;
941
942     /* if they are the same */
943     if (sym1 == sym2)
944         return TRUE ;
945
946     if (sym1->rname[0] && sym2->rname[0]
947         && strcmp (sym1->rname, sym2->rname) == 0)
948         return TRUE;
949
950
951     /* if left is a tmp & right is not */
952     if (IS_ITEMP(op1)  && 
953         !IS_ITEMP(op2) &&
954         sym1->isspilt  &&
955         (sym1->usl.spillLoc == sym2))
956         return TRUE;
957
958     if (IS_ITEMP(op2)  && 
959         !IS_ITEMP(op1) &&
960         sym2->isspilt  &&
961         sym1->level > 0 &&
962         (sym2->usl.spillLoc == sym1))
963         return TRUE ;
964
965     return FALSE ;
966 }
967
968 /*-----------------------------------------------------------------*/
969 /* pic16_sameRegs - two asmops have the same registers                   */
970 /*-----------------------------------------------------------------*/
971 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
972 {
973     int i;
974
975     if (aop1 == aop2)
976         return TRUE ;
977
978     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
979                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
980
981     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
982
983     if (aop1->type != AOP_REG ||
984         aop2->type != AOP_REG )
985         return FALSE ;
986
987     if (aop1->size != aop2->size )
988         return FALSE ;
989
990     for (i = 0 ; i < aop1->size ; i++ )
991         if (aop1->aopu.aop_reg[i] !=
992             aop2->aopu.aop_reg[i] )
993             return FALSE ;
994
995     return TRUE ;
996 }
997
998 /*-----------------------------------------------------------------*/
999 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1000 /*-----------------------------------------------------------------*/
1001 void pic16_aopOp (operand *op, iCode *ic, bool result)
1002 {
1003     asmop *aop;
1004     symbol *sym;
1005     int i;
1006
1007     if (!op)
1008         return ;
1009
1010 //      DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1011
1012     /* if this a literal */
1013     if (IS_OP_LITERAL(op)) {
1014         op->aop = aop = newAsmop(AOP_LIT);
1015         aop->aopu.aop_lit = op->operand.valOperand;
1016         aop->size = getSize(operandType(op));
1017         return;
1018     }
1019
1020     {
1021       sym_link *type = operandType(op);
1022 #if 0
1023       if(IS_PTR_CONST(type))
1024 #else
1025       if(IS_CODEPTR(type))
1026 #endif
1027         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1028     }
1029
1030     /* if already has a asmop then continue */
1031     if (op->aop)
1032         return ;
1033
1034     /* if the underlying symbol has a aop */
1035     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1036       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1037         op->aop = OP_SYMBOL(op)->aop;
1038         return;
1039     }
1040
1041     /* if this is a true symbol */
1042     if (IS_TRUE_SYMOP(op)) {    
1043         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1044       op->aop = aopForSym(ic, op, result);
1045       return ;
1046     }
1047
1048     /* this is a temporary : this has
1049     only four choices :
1050     a) register
1051     b) spillocation
1052     c) rematerialize 
1053     d) conditional   
1054     e) can be a return use only */
1055
1056     sym = OP_SYMBOL(op);
1057
1058         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
1059     /* if the type is a conditional */
1060     if (sym->regType == REG_CND) {
1061         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1062         aop->size = 0;
1063         return;
1064     }
1065
1066     /* if it is spilt then two situations
1067     a) is rematerialize 
1068     b) has a spill location */
1069     if (sym->isspilt || sym->nRegs == 0) {
1070
1071       DEBUGpic16_emitcode(";","%d",__LINE__);
1072         /* rematerialize it NOW */
1073         if (sym->remat) {
1074
1075             sym->aop = op->aop = aop =
1076                                       aopForRemat (op);
1077             aop->size = getSize(sym->type);
1078             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1079             return;
1080         }
1081
1082 #if 1
1083         if (sym->accuse) {
1084             int i;
1085             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1086             aop->size = getSize(sym->type);
1087             for ( i = 0 ; i < 1 ; i++ ) {
1088                 aop->aopu.aop_str[i] = accUse[i];
1089 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1090             }
1091             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1092             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1093             return;  
1094         }
1095 #endif
1096
1097 #if 1
1098         if (sym->ruonly ) {
1099           /*
1100           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1101           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1102           //pic16_allocDirReg (IC_LEFT(ic));
1103           aop->size = getSize(sym->type);
1104           */
1105
1106           unsigned i;
1107
1108           aop = op->aop = sym->aop = newAsmop(AOP_STR);
1109           aop->size = getSize(sym->type);
1110           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1111             aop->aopu.aop_str[i] = fReturn[i];
1112
1113           DEBUGpic16_emitcode(";","%d",__LINE__);
1114           return;
1115         }
1116 #endif
1117         /* else spill location  */
1118         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1119             /* force a new aop if sizes differ */
1120             sym->usl.spillLoc->aop = NULL;
1121         }
1122         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1123                             __FUNCTION__,__LINE__,
1124                             sym->usl.spillLoc->rname,
1125                             sym->rname, sym->usl.spillLoc->offset);
1126
1127         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1128         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1129         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1130                                           getSize(sym->type), 
1131                                           sym->usl.spillLoc->offset, op);
1132         aop->size = getSize(sym->type);
1133
1134         return;
1135     }
1136
1137     {
1138       sym_link *type = operandType(op);
1139 #if 0
1140       if(IS_PTR_CONST(type)) 
1141 #else
1142       if(IS_CODEPTR(type)) 
1143 #endif
1144         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1145     }
1146
1147     /* must be in a register */
1148     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1149     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1150     aop->size = sym->nRegs;
1151     for ( i = 0 ; i < sym->nRegs ;i++)
1152         aop->aopu.aop_reg[i] = sym->regs[i];
1153 }
1154
1155 /*-----------------------------------------------------------------*/
1156 /* pic16_freeAsmop - free up the asmop given to an operand               */
1157 /*----------------------------------------------------------------*/
1158 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1159 {   
1160     asmop *aop ;
1161
1162     if (!op)
1163         aop = aaop;
1164     else 
1165         aop = op->aop;
1166
1167     if (!aop)
1168         return ;
1169
1170     if (aop->freed)
1171         goto dealloc; 
1172
1173     aop->freed = 1;
1174
1175     /* depending on the asmop type only three cases need work AOP_RO
1176        , AOP_R1 && AOP_STK */
1177 #if 1
1178     switch (aop->type) {
1179         case AOP_FSR0 :
1180             if (_G.fsr0Pushed ) {
1181                 if (pop) {
1182                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1183                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1184 //                    pic16_emitcode ("pop","ar0");
1185                     _G.fsr0Pushed--;
1186                 }
1187             }
1188             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1189             break;
1190
1191         case AOP_FSR2 :
1192             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1193             break;
1194
1195         case AOP_R0 :
1196             if (_G.r0Pushed ) {
1197                 if (pop) {
1198                     pic16_emitcode ("pop","ar0");     
1199                     _G.r0Pushed--;
1200                 }
1201             }
1202             bitVectUnSetBit(ic->rUsed,R0_IDX);
1203             break;
1204
1205         case AOP_R1 :
1206             if (_G.r1Pushed ) {
1207                 if (pop) {
1208                     pic16_emitcode ("pop","ar1");
1209                     _G.r1Pushed--;
1210                 }
1211             }
1212             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1213             break;
1214
1215         case AOP_STK :
1216         {
1217             int sz = aop->size;    
1218             int stk = aop->aopu.aop_stk + aop->size;
1219             bitVectUnSetBit(ic->rUsed,R0_IDX);
1220             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1221
1222             getFreePtr(ic,&aop,FALSE);
1223             
1224             if (options.stack10bit)
1225             {
1226                 /* I'm not sure what to do here yet... */
1227                 /* #STUB */
1228                 fprintf(stderr, 
1229                         "*** Warning: probably generating bad code for "
1230                         "10 bit stack mode.\n");
1231             }
1232             
1233             if (stk) {
1234                 pic16_emitcode ("mov","a,_bp");
1235                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1236                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1237             } else {
1238                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1239             }
1240
1241             while (sz--) {
1242                 pic16_emitcode("pop","acc");
1243                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1244                 if (!sz) break;
1245                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1246             }
1247             op->aop = aop;
1248             pic16_freeAsmop(op,NULL,ic,TRUE);
1249             if (_G.r0Pushed) {
1250                 pic16_emitcode("pop","ar0");
1251                 _G.r0Pushed--;
1252             }
1253
1254             if (_G.r1Pushed) {
1255                 pic16_emitcode("pop","ar1");
1256                 _G.r1Pushed--;
1257             }       
1258         }
1259     }
1260 #endif
1261
1262 dealloc:
1263     /* all other cases just dealloc */
1264     if (op ) {
1265         op->aop = NULL;
1266         if (IS_SYMOP(op)) {
1267             OP_SYMBOL(op)->aop = NULL;    
1268             /* if the symbol has a spill */
1269             if (SPIL_LOC(op))
1270                 SPIL_LOC(op)->aop = NULL;
1271         }
1272     }
1273 }
1274
1275 /*-----------------------------------------------------------------*/
1276 /* pic16_aopGet - for fetching value of the aop                          */
1277 /*-----------------------------------------------------------------*/
1278 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1279 {
1280     char *s = buffer ;
1281     char *rs;
1282
1283     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1284
1285     /* offset is greater than size then zero */
1286     if (offset > (aop->size - 1) &&
1287         aop->type != AOP_LIT)
1288         return zero;
1289
1290     /* depending on type */
1291     switch (aop->type) {
1292
1293     case AOP_FSR0:
1294     case AOP_FSR2:
1295       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1296       rs = Safe_calloc(1, strlen(s)+1);
1297       strcpy(rs, s);
1298       return (rs);
1299       
1300 #if 0
1301       /* if we need to increment it */
1302       while (offset > aop->coff)
1303         {
1304           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1305           aop->coff++;
1306         }
1307
1308       while (offset < aop->coff)
1309         {
1310           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1311           aop->coff--;
1312         }
1313       aop->coff = offset;
1314       if (aop->paged)
1315         {
1316           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1317           return (dname ? "acc" : "a");
1318         }
1319       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1320       rs = Safe_calloc (1, strlen (s) + 1);
1321       strcpy (rs, s);
1322       return rs;
1323 #endif
1324
1325         
1326     case AOP_IMMD:
1327         if (bit16) 
1328             sprintf (s,"%s",aop->aopu.aop_immd);
1329         else
1330             if (offset) 
1331                 sprintf(s,"(%s >> %d)",
1332                         aop->aopu.aop_immd,
1333                         offset*8);
1334             else
1335                 sprintf(s,"%s",
1336                         aop->aopu.aop_immd);
1337         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1338         rs = Safe_calloc(1,strlen(s)+1);
1339         strcpy(rs,s);   
1340         return rs;
1341         
1342     case AOP_DIR:
1343       if (offset) {
1344         sprintf(s,"(%s + %d)",
1345                 aop->aopu.aop_dir,
1346                 offset);
1347         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1348       } else
1349             sprintf(s,"%s",aop->aopu.aop_dir);
1350         rs = Safe_calloc(1,strlen(s)+1);
1351         strcpy(rs,s);   
1352         return rs;
1353         
1354     case AOP_REG:
1355       //if (dname) 
1356       //    return aop->aopu.aop_reg[offset]->dname;
1357       //else
1358             return aop->aopu.aop_reg[offset]->name;
1359         
1360     case AOP_CRY:
1361       //pic16_emitcode(";","%d",__LINE__);
1362       return aop->aopu.aop_dir;
1363         
1364     case AOP_ACC:
1365         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1366 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1367 //        assert( 0 );
1368 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1369         rs = Safe_strdup("WREG");
1370         return (rs);
1371
1372     case AOP_LIT:
1373         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1374         rs = Safe_calloc(1,strlen(s)+1);
1375         strcpy(rs,s);   
1376         return rs;
1377         
1378     case AOP_STR:
1379         aop->coff = offset ;
1380         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1381             dname)
1382             return "acc";
1383         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1384         
1385         return aop->aopu.aop_str[offset];
1386         
1387     case AOP_PCODE:
1388       {
1389         pCodeOp *pcop = aop->aopu.pcop;
1390         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1391         if(pcop->name) {
1392           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1393           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1394           sprintf(s,"%s", pcop->name);
1395         } else
1396           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1397
1398       }
1399       rs = Safe_calloc(1,strlen(s)+1);
1400       strcpy(rs,s);   
1401       return rs;
1402
1403       case AOP_STK:
1404 //        pCodeOp *pcop = aop->aop
1405         break;
1406
1407     }
1408
1409     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1410     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1411            "aopget got unsupported aop->type");
1412     exit(0);
1413 }
1414
1415
1416 /*-----------------------------------------------------------------*/
1417 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1418 /*-----------------------------------------------------------------*/
1419 pCodeOp *pic16_popGetTempReg(void)
1420 {
1421   pCodeOp *pcop;
1422   symbol *cfunc;
1423
1424 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1425
1426         cfunc = currFunc;
1427         currFunc = NULL;
1428
1429         pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1430         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1431                 PCOR(pcop)->r->wasUsed=1;
1432                 PCOR(pcop)->r->isFree=0;
1433
1434                 /* push value on stack */
1435                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1436         }
1437
1438         currFunc = cfunc;
1439
1440   return pcop;
1441 }
1442
1443 /*-----------------------------------------------------------------*/
1444 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1445 /*-----------------------------------------------------------------*/
1446 void pic16_popReleaseTempReg(pCodeOp *pcop)
1447 {
1448         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1449
1450         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1451                 PCOR(pcop)->r->isFree = 1;
1452                 
1453                 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1454         }
1455 }
1456 /*-----------------------------------------------------------------*/
1457 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1458 /*-----------------------------------------------------------------*/
1459 pCodeOp *pic16_popGetLabel(unsigned int key)
1460 {
1461
1462   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1463
1464   if(key>max_key)
1465     max_key = key;
1466
1467   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1468 }
1469
1470 /*-----------------------------------------------------------------*/
1471 /* pic16_popCopyReg - copy a pcode operator                              */
1472 /*-----------------------------------------------------------------*/
1473 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1474 {
1475   pCodeOpReg *pcor;
1476
1477   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1478   pcor->pcop.type = pc->pcop.type;
1479   if(pc->pcop.name) {
1480     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1481       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1482   } else
1483     pcor->pcop.name = NULL;
1484
1485   pcor->r = pc->r;
1486   pcor->rIdx = pc->rIdx;
1487   pcor->r->wasUsed=1;
1488
1489 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1490
1491   return PCOP(pcor);
1492 }
1493
1494 /*-----------------------------------------------------------------*/
1495 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1496 /*-----------------------------------------------------------------*/
1497 pCodeOp *pic16_popGetLit(unsigned int lit)
1498 {
1499   return pic16_newpCodeOpLit(lit);
1500 }
1501
1502 /*-----------------------------------------------------------------*/
1503 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1504 /*-----------------------------------------------------------------*/
1505 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1506 {
1507   return pic16_newpCodeOpLit2(lit, arg2);
1508 }
1509
1510
1511 /*-----------------------------------------------------------------*/
1512 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1513 /*-----------------------------------------------------------------*/
1514 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1515 {
1516   return pic16_newpCodeOpImmd(name, offset,index, 0);
1517 }
1518
1519
1520 /*-----------------------------------------------------------------*/
1521 /* pic16_popGet - asm operator to pcode operator conversion              */
1522 /*-----------------------------------------------------------------*/
1523 pCodeOp *pic16_popGetWithString(char *str)
1524 {
1525   pCodeOp *pcop;
1526
1527
1528   if(!str) {
1529     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1530     exit (1);
1531   }
1532
1533   pcop = pic16_newpCodeOp(str,PO_STR);
1534
1535   return pcop;
1536 }
1537
1538 /*-----------------------------------------------------------------*/
1539 /* pic16_popRegFromString -                                        */
1540 /*-----------------------------------------------------------------*/
1541 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1542 {
1543
1544   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1545   pcop->type = PO_DIR;
1546
1547   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1548   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1549
1550   if(!str)
1551     str = "BAD_STRING";
1552
1553   pcop->name = Safe_calloc(1,strlen(str)+1);
1554   strcpy(pcop->name,str);
1555
1556   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1557
1558   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1559   if(PCOR(pcop)->r == NULL) {
1560 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1561 //              __FUNCTION__, __LINE__, str, size, offset);
1562
1563
1564 //    PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1565         fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1566
1567 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1568   } else {
1569 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d",__LINE__,pcop->name,size,offset);
1570   }
1571   PCOR(pcop)->instance = offset;
1572
1573   return pcop;
1574 }
1575
1576 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1577 {
1578   pCodeOp *pcop;
1579
1580 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1581
1582         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1583         PCOR(pcop)->rIdx = rIdx;
1584         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1585
1586         PCOR(pcop)->r->isFree = 0;
1587         PCOR(pcop)->r->wasUsed = 1;
1588
1589         pcop->type = PCOR(pcop)->r->pc_type;
1590
1591   return pcop;
1592 }
1593
1594 /*---------------------------------------------------------------------------------*/
1595 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1596 /*                 VR 030601                                                       */
1597 /*---------------------------------------------------------------------------------*/
1598 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1599 {
1600   pCodeOpReg2 *pcop2;
1601   pCodeOp *temp;
1602   
1603         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1604
1605         /* comment the following check, so errors to throw up */
1606 //      if(!pcop2)return NULL;
1607
1608         temp = pic16_popGet(aop_dst, offset);
1609         pcop2->pcop2 = temp;
1610         
1611   return PCOP(pcop2);
1612 }
1613
1614
1615
1616 /*--------------------------------------------------------------------------------.-*/
1617 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1618 /*                  VR 030601 , adapted by Hans Dorn                                */
1619 /*--------------------------------------------------------------------------------.-*/
1620 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1621 {
1622   pCodeOpReg2 *pcop2;
1623  
1624         pcop2 = (pCodeOpReg2 *)src;
1625         pcop2->pcop2 = dst;
1626         
1627         return PCOP(pcop2);
1628 }
1629
1630
1631
1632 /*---------------------------------------------------------------------------------*/
1633 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1634 /*                     movff instruction                                           */
1635 /*---------------------------------------------------------------------------------*/
1636 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1637 {
1638   pCodeOpReg2 *pcop2;
1639
1640         if(!noalloc) {
1641                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1642                 pcop2->pcop2 = pic16_popCopyReg(dst);
1643         } else {
1644                 /* the pCodeOp may be already allocated */
1645                 pcop2 = (pCodeOpReg2 *)(src);
1646                 pcop2->pcop2 = (pCodeOp *)(dst);
1647         }
1648
1649   return PCOP(pcop2);
1650 }
1651
1652
1653 /*-----------------------------------------------------------------*/
1654 /* pic16_popGet - asm operator to pcode operator conversion              */
1655 /*-----------------------------------------------------------------*/
1656 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1657 {
1658   //char *s = buffer ;
1659   char *rs;
1660   pCodeOp *pcop;
1661
1662     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1663     /* offset is greater than
1664     size then zero */
1665
1666 //    if (offset > (aop->size - 1) &&
1667 //        aop->type != AOP_LIT)
1668 //      return NULL;  //zero;
1669
1670     /* depending on type */
1671     switch (aop->type) {
1672         
1673     case AOP_R0:
1674     case AOP_R1:
1675     case AOP_DPTR:
1676     case AOP_DPTR2:
1677         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1678         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1679         assert( 0 );
1680         return NULL;
1681
1682
1683     case AOP_FSR0:
1684     case AOP_FSR2:
1685       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1686       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
1687       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1688       PCOR(pcop)->r->wasUsed = 1;
1689       PCOR(pcop)->r->isFree = 0;
1690       
1691       PCOR(pcop)->instance = offset;
1692       pcop->type = PCOR(pcop)->r->pc_type;
1693       return (pcop);
1694
1695     case AOP_IMMD:
1696       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1697       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1698
1699     case AOP_ACC:
1700       {
1701         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1702
1703         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1704
1705         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1706         
1707         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1708         PCOR(pcop)->rIdx = rIdx;
1709         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1710         PCOR(pcop)->r->wasUsed=1;
1711         PCOR(pcop)->r->isFree=0;
1712
1713         PCOR(pcop)->instance = offset;
1714         pcop->type = PCOR(pcop)->r->pc_type;
1715 //      rs = aop->aopu.aop_reg[offset]->name;
1716 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1717         return pcop;
1718
1719
1720 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1721 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1722
1723 //      assert( 0 );
1724       }
1725         
1726     case AOP_DIR:
1727       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1728       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1729         
1730     case AOP_REG:
1731       {
1732         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1733
1734         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1735         
1736         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1737 //      pcop->type = PO_GPR_REGISTER;
1738         PCOR(pcop)->rIdx = rIdx;
1739         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
1740         PCOR(pcop)->r->wasUsed=1;
1741         PCOR(pcop)->r->isFree=0;
1742
1743         PCOR(pcop)->instance = offset;
1744         pcop->type = PCOR(pcop)->r->pc_type;
1745         rs = aop->aopu.aop_reg[offset]->name;
1746         DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1747         return pcop;
1748       }
1749
1750     case AOP_CRY:
1751         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1752
1753       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1754       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1755       //if(PCOR(pcop)->r == NULL)
1756       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1757       return pcop;
1758         
1759     case AOP_LIT:
1760         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1761       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1762
1763     case AOP_STR:
1764       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1765       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1766
1767       /*
1768       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1769       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1770       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1771       pcop->type = PCOR(pcop)->r->pc_type;
1772       pcop->name = PCOR(pcop)->r->name;
1773
1774       return pcop;
1775       */
1776
1777     case AOP_PCODE:
1778       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1779                           __LINE__, 
1780                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1781       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1782 #if 1
1783         switch( aop->aopu.pcop->type ) {
1784                 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1785                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1786                 default:
1787                         assert( 0 );    /* should never reach here */;
1788         }
1789 #else
1790       PCOI(pcop)->offset = offset;
1791 #endif
1792       return pcop;
1793     }
1794
1795     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1796            "pic16_popGet got unsupported aop->type");
1797     exit(0);
1798 }
1799 /*-----------------------------------------------------------------*/
1800 /* pic16_aopPut - puts a string for a aop                                */
1801 /*-----------------------------------------------------------------*/
1802 void pic16_aopPut (asmop *aop, char *s, int offset)
1803 {
1804     char *d = buffer ;
1805     symbol *lbl ;
1806
1807     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1808
1809     if (aop->size && offset > ( aop->size - 1)) {
1810         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1811                "pic16_aopPut got offset > aop->size");
1812         exit(0);
1813     }
1814
1815     /* will assign value to value */
1816     /* depending on where it is ofcourse */
1817     switch (aop->type) {
1818     case AOP_DIR:
1819       if (offset) {
1820         sprintf(d,"(%s + %d)",
1821                 aop->aopu.aop_dir,offset);
1822         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1823
1824       } else
1825             sprintf(d,"%s",aop->aopu.aop_dir);
1826         
1827         if (strcmp(d,s)) {
1828           DEBUGpic16_emitcode(";","%d",__LINE__);
1829           if(strcmp(s,"W"))
1830             pic16_emitcode("movf","%s,w",s);
1831           pic16_emitcode("movwf","%s",d);
1832
1833           if(strcmp(s,"W")) {
1834             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1835             if(offset >= aop->size) {
1836               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1837               break;
1838             } else
1839               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1840           }
1841
1842           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1843
1844
1845         }
1846         break;
1847         
1848     case AOP_REG:
1849       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1850         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1851           /*
1852             if (*s == '@'           ||
1853                 strcmp(s,"r0") == 0 ||
1854                 strcmp(s,"r1") == 0 ||
1855                 strcmp(s,"r2") == 0 ||
1856                 strcmp(s,"r3") == 0 ||
1857                 strcmp(s,"r4") == 0 ||
1858                 strcmp(s,"r5") == 0 ||
1859                 strcmp(s,"r6") == 0 || 
1860                 strcmp(s,"r7") == 0 )
1861                 pic16_emitcode("mov","%s,%s  ; %d",
1862                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1863             else
1864           */
1865
1866           if(strcmp(s,"W")==0 )
1867             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1868
1869           pic16_emitcode("movwf","%s",
1870                    aop->aopu.aop_reg[offset]->name);
1871
1872           if(strcmp(s,zero)==0) {
1873             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1874
1875           } else if(strcmp(s,"W")==0) {
1876             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1877             pcop->type = PO_GPR_REGISTER;
1878
1879             PCOR(pcop)->rIdx = -1;
1880             PCOR(pcop)->r = NULL;
1881
1882             DEBUGpic16_emitcode(";","%d",__LINE__);
1883             pcop->name = Safe_strdup(s);
1884             pic16_emitpcode(POC_MOVFW,pcop);
1885             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1886           } else if(strcmp(s,one)==0) {
1887             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1888             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1889           } else {
1890             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1891           }
1892         }
1893         break;
1894         
1895     case AOP_DPTR:
1896     case AOP_DPTR2:
1897     
1898     if (aop->type == AOP_DPTR2)
1899     {
1900         genSetDPTR(1);
1901     }
1902     
1903         if (aop->code) {
1904             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1905                    "pic16_aopPut writting to code space");
1906             exit(0);
1907         }
1908         
1909         while (offset > aop->coff) {
1910             aop->coff++;
1911             pic16_emitcode ("inc","dptr");
1912         }
1913         
1914         while (offset < aop->coff) {
1915             aop->coff-- ;
1916             pic16_emitcode("lcall","__decdptr");
1917         }
1918         
1919         aop->coff = offset;
1920         
1921         /* if not in accumulater */
1922         MOVA(s);        
1923         
1924         pic16_emitcode ("movx","@dptr,a");
1925         
1926     if (aop->type == AOP_DPTR2)
1927     {
1928         genSetDPTR(0);
1929     }
1930         break;
1931         
1932     case AOP_R0:
1933     case AOP_R1:
1934         while (offset > aop->coff) {
1935             aop->coff++;
1936             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1937         }
1938         while (offset < aop->coff) {
1939             aop->coff-- ;
1940             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1941         }
1942         aop->coff = offset;
1943         
1944         if (aop->paged) {
1945             MOVA(s);           
1946             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1947             
1948         } else
1949             if (*s == '@') {
1950                 MOVA(s);
1951                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1952             } else
1953                 if (strcmp(s,"r0") == 0 ||
1954                     strcmp(s,"r1") == 0 ||
1955                     strcmp(s,"r2") == 0 ||
1956                     strcmp(s,"r3") == 0 ||
1957                     strcmp(s,"r4") == 0 ||
1958                     strcmp(s,"r5") == 0 ||
1959                     strcmp(s,"r6") == 0 || 
1960                     strcmp(s,"r7") == 0 ) {
1961                     char buffer[10];
1962                     sprintf(buffer,"a%s",s);
1963                     pic16_emitcode("mov","@%s,%s",
1964                              aop->aopu.aop_ptr->name,buffer);
1965                 } else
1966                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1967         
1968         break;
1969         
1970     case AOP_STK:
1971         if (strcmp(s,"a") == 0)
1972             pic16_emitcode("push","acc");
1973         else
1974             pic16_emitcode("push","%s",s);
1975         
1976         break;
1977         
1978     case AOP_CRY:
1979         /* if bit variable */
1980         if (!aop->aopu.aop_dir) {
1981             pic16_emitcode("clr","a");
1982             pic16_emitcode("rlc","a");
1983         } else {
1984             if (s == zero) 
1985                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1986             else
1987                 if (s == one)
1988                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1989                 else
1990                     if (!strcmp(s,"c"))
1991                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1992                     else {
1993                         lbl = newiTempLabel(NULL);
1994                         
1995                         if (strcmp(s,"a")) {
1996                             MOVA(s);
1997                         }
1998                         pic16_emitcode("clr","c");
1999                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2000                         pic16_emitcode("cpl","c");
2001                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2002                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2003                     }
2004         }
2005         break;
2006         
2007     case AOP_STR:
2008         aop->coff = offset;
2009         if (strcmp(aop->aopu.aop_str[offset],s))
2010             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2011         break;
2012         
2013     case AOP_ACC:
2014         aop->coff = offset;
2015         if (!offset && (strcmp(s,"acc") == 0))
2016             break;
2017         
2018         if (strcmp(aop->aopu.aop_str[offset],s))
2019             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2020         break;
2021
2022     default :
2023         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2024                "pic16_aopPut got unsupported aop->type");
2025         exit(0);    
2026     }    
2027
2028 }
2029
2030 /*-----------------------------------------------------------------*/
2031 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
2032 /*-----------------------------------------------------------------*/
2033 static void mov2w (asmop *aop, int offset)
2034 {
2035
2036 //  if(!aop)
2037 //    return;
2038
2039         DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2040
2041         if(is_LitAOp(aop))
2042                 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2043         else
2044                 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2045
2046 }
2047
2048
2049 /* push pcop into stack */
2050 void pic16_pushpCodeOp(pCodeOp *pcop)
2051 {
2052 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2053         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
2054 }
2055
2056 /* pop pcop from stack */
2057 void pic16_poppCodeOp(pCodeOp *pcop)
2058 {
2059         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
2060 }
2061
2062
2063 /*-----------------------------------------------------------------*/
2064 /* pushw - pushes wreg to stack                                    */
2065 /*-----------------------------------------------------------------*/
2066 void pushw(void)
2067 {
2068         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2069         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2070 }
2071
2072                 
2073 /*-----------------------------------------------------------------*/
2074 /* pushaop - pushes aop to stack                                   */
2075 /*-----------------------------------------------------------------*/
2076 void pushaop(asmop *aop, int offset)
2077 {
2078         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2079         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
2080 }
2081
2082 /*-----------------------------------------------------------------*/
2083 /* popaop - pops aop from stack                                    */
2084 /*-----------------------------------------------------------------*/
2085 void popaop(asmop *aop, int offset)
2086 {
2087         DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2088         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
2089 }
2090
2091 void popaopidx(asmop *aop, int offset, int index)
2092 {
2093   int ofs=1;
2094
2095         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2096
2097         if(STACK_MODEL_LARGE)ofs++;
2098
2099         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2100         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
2101 }
2102
2103 /*-----------------------------------------------------------------*/
2104 /* reAdjustPreg - points a register back to where it should        */
2105 /*-----------------------------------------------------------------*/
2106 static void reAdjustPreg (asmop *aop)
2107 {
2108     int size ;
2109
2110     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2111     aop->coff = 0;
2112     if ((size = aop->size) <= 1)
2113         return ;
2114     size-- ;
2115     switch (aop->type) {
2116         case AOP_R0 :
2117         case AOP_R1 :
2118             while (size--)
2119                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2120             break;          
2121         case AOP_DPTR :
2122         case AOP_DPTR2:
2123             if (aop->type == AOP_DPTR2)
2124             {
2125                 genSetDPTR(1);
2126             } 
2127             while (size--)
2128             {
2129                 pic16_emitcode("lcall","__decdptr");
2130             }
2131                 
2132             if (aop->type == AOP_DPTR2)
2133             {
2134                 genSetDPTR(0);
2135             }                
2136             break;  
2137
2138     }   
2139
2140 }
2141
2142
2143 #if 0
2144 /*-----------------------------------------------------------------*/
2145 /* opIsGptr: returns non-zero if the passed operand is             */   
2146 /* a generic pointer type.                                         */
2147 /*-----------------------------------------------------------------*/ 
2148 static int opIsGptr(operand *op)
2149 {
2150     sym_link *type = operandType(op);
2151     
2152     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2153     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2154     {
2155         return 1;
2156     }
2157     return 0;        
2158 }
2159 #endif
2160
2161 /*-----------------------------------------------------------------*/
2162 /* pic16_getDataSize - get the operand data size                         */
2163 /*-----------------------------------------------------------------*/
2164 int pic16_getDataSize(operand *op)
2165 {
2166     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2167
2168
2169     return AOP_SIZE(op);
2170
2171     // tsd- in the pic port, the genptr size is 1, so this code here
2172     // fails. ( in the 8051 port, the size was 4).
2173 #if 0
2174     int size;
2175     size = AOP_SIZE(op);
2176     if (size == GPTRSIZE)
2177     {
2178         sym_link *type = operandType(op);
2179         if (IS_GENPTR(type))
2180         {
2181             /* generic pointer; arithmetic operations
2182              * should ignore the high byte (pointer type).
2183              */
2184             size--;
2185     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2186         }
2187     }
2188     return size;
2189 #endif
2190 }
2191
2192 /*-----------------------------------------------------------------*/
2193 /* pic16_outAcc - output Acc                                             */
2194 /*-----------------------------------------------------------------*/
2195 void pic16_outAcc(operand *result)
2196 {
2197   int size,offset;
2198   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2199   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2200
2201
2202   size = pic16_getDataSize(result);
2203   if(size){
2204     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2205     size--;
2206     offset = 1;
2207     /* unsigned or positive */
2208     while(size--)
2209       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2210   }
2211
2212 }
2213
2214 /*-----------------------------------------------------------------*/
2215 /* pic16_outBitC - output a bit C                                  */
2216 /*                 Move to result the value of Carry flag -- VR    */
2217 /*-----------------------------------------------------------------*/
2218 void pic16_outBitC(operand *result)
2219 {
2220   int i;
2221
2222     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2223     /* if the result is bit */
2224     if (AOP_TYPE(result) == AOP_CRY) {
2225         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2226         pic16_aopPut(AOP(result),"c",0);
2227     } else {
2228
2229         i = AOP_SIZE(result);
2230         while(i--) {
2231                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2232         }
2233         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2234         
2235 /*
2236         pic16_emitcode("clr","a  ; %d", __LINE__);
2237         pic16_emitcode("rlc","a");
2238         pic16_outAcc(result);
2239 */
2240     }
2241 }
2242
2243 /*-----------------------------------------------------------------*/
2244 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2245 /*-----------------------------------------------------------------*/
2246 void pic16_toBoolean(operand *oper)
2247 {
2248     int size = AOP_SIZE(oper) - 1;
2249     int offset = 1;
2250
2251     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2252
2253     if ( AOP_TYPE(oper) != AOP_ACC) {
2254       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2255     }
2256     while (size--) {
2257       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2258     }
2259 }
2260
2261
2262 #if !defined(GEN_Not)
2263 /*-----------------------------------------------------------------*/
2264 /* genNot - generate code for ! operation                          */
2265 /*-----------------------------------------------------------------*/
2266 static void pic16_genNot (iCode *ic)
2267 {
2268   symbol *tlbl;
2269   int size;
2270
2271   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2272   /* assign asmOps to operand & result */
2273   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2274   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2275
2276   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2277   /* if in bit space then a special case */
2278   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2279     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2280       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2281       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2282     } else {
2283       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2284       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2285       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2286     }
2287     goto release;
2288   }
2289
2290   size = AOP_SIZE(IC_LEFT(ic));
2291   if(size == 1) {
2292     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2293     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2294     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2295     goto release;
2296   }
2297   pic16_toBoolean(IC_LEFT(ic));
2298
2299   tlbl = newiTempLabel(NULL);
2300   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2301   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2302   pic16_outBitC(IC_RESULT(ic));
2303
2304  release:    
2305   /* release the aops */
2306   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2307   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2308 }
2309 #endif
2310
2311
2312 #if !defined(GEN_Cpl)
2313 /*-----------------------------------------------------------------*/
2314 /* genCpl - generate code for complement                           */
2315 /*-----------------------------------------------------------------*/
2316 static void pic16_genCpl (iCode *ic)
2317 {
2318     int offset = 0;
2319     int size ;
2320
2321
2322     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2323     /* assign asmOps to operand & result */
2324     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2325     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2326
2327     /* if both are in bit space then 
2328     a special case */
2329     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2330         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2331
2332         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2333         pic16_emitcode("cpl","c"); 
2334         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2335         goto release; 
2336     } 
2337
2338     size = AOP_SIZE(IC_RESULT(ic));
2339     while (size--) {
2340 /*
2341         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2342         MOVA(l);       
2343         pic16_emitcode("cpl","a");
2344         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2345 */
2346         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2347               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2348         } else {
2349                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2350                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2351         }
2352         offset++;
2353
2354     }
2355
2356
2357 release:
2358     /* release the aops */
2359     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2360     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2361 }
2362 #endif
2363
2364 /*-----------------------------------------------------------------*/
2365 /* genUminusFloat - unary minus for floating points                */
2366 /*-----------------------------------------------------------------*/
2367 static void genUminusFloat(operand *op,operand *result)
2368 {
2369     int size ,offset =0 ;
2370     char *l;
2371
2372     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2373     /* for this we just need to flip the 
2374     first it then copy the rest in place */
2375     size = AOP_SIZE(op) - 1;
2376     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2377
2378     MOVA(l);    
2379
2380     pic16_emitcode("cpl","acc.7");
2381     pic16_aopPut(AOP(result),"a",3);    
2382
2383     while(size--) {
2384         pic16_aopPut(AOP(result),
2385                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2386                offset);
2387         offset++;
2388     }          
2389 }
2390
2391 /*-----------------------------------------------------------------*/
2392 /* genUminus - unary minus code generation                         */
2393 /*-----------------------------------------------------------------*/
2394 static void genUminus (iCode *ic)
2395 {
2396   int size, i;
2397   sym_link *optype, *rtype;
2398
2399         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2400         
2401         /* assign asmops */
2402         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2403         pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2404
2405         /* if both in bit space then special case */
2406         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2407                 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2408
2409                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2410                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2411                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2412                 
2413                 goto release; 
2414         } 
2415
2416         optype = operandType(IC_LEFT(ic));
2417         rtype = operandType(IC_RESULT(ic));
2418
2419         /* if float then do float stuff */
2420         if (IS_FLOAT(optype)) {
2421                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2422                 goto release;
2423         }
2424
2425         /* otherwise subtract from zero by taking the 2's complement */
2426         size = AOP_SIZE(IC_LEFT(ic));
2427
2428         for(i=0; i<size; i++) {
2429                 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2430                         pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2431                 else {
2432                         pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2433                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2434                 }
2435         }
2436
2437         pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2438         for(i=1; i<size; i++) {
2439                 emitSKPNZ;
2440                 pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2441         }
2442
2443 release:
2444         /* release the aops */
2445         pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2446         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2447 }
2448
2449 /*-----------------------------------------------------------------*/
2450 /* saveRegisters - will look for a call and save the registers     */
2451 /*-----------------------------------------------------------------*/
2452 static void saveRegisters(iCode *lic) 
2453 {
2454     int i;
2455     iCode *ic;
2456     bitVect *rsave;
2457     sym_link *dtype;
2458
2459     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2460     /* look for call */
2461     for (ic = lic ; ic ; ic = ic->next) 
2462         if (ic->op == CALL || ic->op == PCALL)
2463             break;
2464
2465     if (!ic) {
2466         fprintf(stderr,"found parameter push with no function call\n");
2467         return ;
2468     }
2469
2470     /* if the registers have been saved already then
2471     do nothing */
2472     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2473         return ;
2474
2475     /* find the registers in use at this time 
2476     and push them away to safety */
2477     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2478                           ic->rUsed);
2479
2480     ic->regsSaved = 1;
2481     if (options.useXstack) {
2482         if (bitVectBitValue(rsave,R0_IDX))
2483             pic16_emitcode("mov","b,r0");
2484         pic16_emitcode("mov","r0,%s",spname);
2485         for (i = 0 ; i < pic16_nRegs ; i++) {
2486             if (bitVectBitValue(rsave,i)) {
2487                 if (i == R0_IDX)
2488                     pic16_emitcode("mov","a,b");
2489                 else
2490                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2491                 pic16_emitcode("movx","@r0,a");
2492                 pic16_emitcode("inc","r0");
2493             }
2494         }
2495         pic16_emitcode("mov","%s,r0",spname);
2496         if (bitVectBitValue(rsave,R0_IDX))
2497             pic16_emitcode("mov","r0,b");           
2498     }// else
2499     //for (i = 0 ; i < pic16_nRegs ; i++) {
2500     //    if (bitVectBitValue(rsave,i))
2501     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2502     //}
2503
2504     dtype = operandType(IC_LEFT(ic));
2505     if (currFunc && dtype && 
2506         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2507         IFFUNC_ISISR(currFunc->type) &&
2508         !ic->bankSaved) 
2509
2510         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2511
2512 }
2513 /*-----------------------------------------------------------------*/
2514 /* unsaveRegisters - pop the pushed registers                      */
2515 /*-----------------------------------------------------------------*/
2516 static void unsaveRegisters (iCode *ic)
2517 {
2518     int i;
2519     bitVect *rsave;
2520
2521     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2522     /* find the registers in use at this time 
2523     and push them away to safety */
2524     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2525                           ic->rUsed);
2526     
2527     if (options.useXstack) {
2528         pic16_emitcode("mov","r0,%s",spname);   
2529         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2530             if (bitVectBitValue(rsave,i)) {
2531                 pic16_emitcode("dec","r0");
2532                 pic16_emitcode("movx","a,@r0");
2533                 if (i == R0_IDX)
2534                     pic16_emitcode("mov","b,a");
2535                 else
2536                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2537             }       
2538
2539         }
2540         pic16_emitcode("mov","%s,r0",spname);
2541         if (bitVectBitValue(rsave,R0_IDX))
2542             pic16_emitcode("mov","r0,b");
2543     } //else
2544     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2545     //    if (bitVectBitValue(rsave,i))
2546     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2547     //}
2548
2549 }  
2550
2551 #if 0  // patch 14
2552 /*-----------------------------------------------------------------*/
2553 /* pushSide -                                                      */
2554 /*-----------------------------------------------------------------*/
2555 static void pushSide(operand * oper, int size)
2556 {
2557         int offset = 0;
2558     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2559         while (size--) {
2560                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2561                 if (AOP_TYPE(oper) != AOP_REG &&
2562                     AOP_TYPE(oper) != AOP_DIR &&
2563                     strcmp(l,"a") ) {
2564                         pic16_emitcode("mov","a,%s",l);
2565                         pic16_emitcode("push","acc");
2566                 } else
2567                         pic16_emitcode("push","%s",l);
2568         }
2569 }
2570 #endif // patch 14
2571
2572 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2573 {
2574 //              (AOP(left)->aopu.pcop->type == PO_DIR)?
2575
2576         if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2577                 pic16_emitpcode(POC_MOVFW, src);
2578                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2579         } else {
2580                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2581                         src, pic16_popGet(AOP(op), offset)));
2582         }
2583 }
2584
2585
2586 /*-----------------------------------------------------------------*/
2587 /* assignResultValue - assign results to oper, rescall==1 is       */
2588 /*                     called from genCall() or genPCall()         */
2589 /*-----------------------------------------------------------------*/
2590 static void assignResultValue(operand * oper, int rescall)
2591 {
2592   int size = AOP_SIZE(oper);
2593
2594         DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2595         DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2596
2597         if(rescall) {
2598                 /* assign result from a call/pcall function() */
2599                 
2600                 /* function results are stored in a special order,
2601                  * see top of file with Function return policy, or manual */
2602
2603                 if(size <= 4) {
2604                         /* 8-bits, result in WREG */
2605                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2606                         
2607                         if(size>1) {
2608                                 /* 16-bits, result in PRODL:WREG */
2609                                 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2610                         }
2611                         
2612                         if(size>2) {
2613                                 /* 24-bits, result in PRODH:PRODL:WREG */
2614                                 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2615                         }
2616                         
2617                         if(size>3) {
2618                                 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2619                                 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2620                         }
2621                 } else {
2622                         /* >32-bits, result on stack, and FSR0 points to beginning.
2623                          * Fix stack when done */
2624                          /* FIXME FIXME */
2625                         while (size--) {
2626 //                              DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2627 //                              DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2628                 
2629                                 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2630                                 GpsuedoStkPtr++;
2631                         }
2632                         
2633                         /* fix stack */
2634                         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2635                         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2636                         if(STACK_MODEL_LARGE) {
2637                                 emitSKPNC;
2638                                 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2639                         }
2640                 }                       
2641         } else {        
2642                 if(!GpsuedoStkPtr) {
2643 //                      DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2644                         /* The last byte in the assignment is in W */
2645                         size--;
2646                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2647                         GpsuedoStkPtr++;
2648                 }
2649
2650                 while (size--) {
2651 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2652 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2653                 
2654                         popaopidx(AOP(oper), size, GpsuedoStkPtr);
2655                         GpsuedoStkPtr++;
2656
2657 #if 0
2658 #if STACK_SUPPORT
2659                 if(!USE_STACK)
2660                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2661 #else
2662                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2663 #endif
2664 #endif
2665
2666                 }
2667         }
2668                 
2669 }
2670
2671
2672 /*-----------------------------------------------------------------*/
2673 /* genIpush - genrate code for pushing this gets a little complex  */
2674 /*-----------------------------------------------------------------*/
2675 static void genIpush (iCode *ic)
2676 {
2677   int size, offset=0;
2678
2679   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2680
2681
2682         pic16_aopOp(IC_LEFT(ic), ic, FALSE);
2683         
2684
2685         size = AOP_SIZE( IC_LEFT(ic) );
2686         
2687         while(size--) {
2688                 mov2w( AOP(IC_LEFT(ic)), offset );
2689                 pushw();
2690                 offset++;
2691         }
2692         
2693 #if 0
2694     int size, offset = 0 ;
2695     char *l;
2696
2697
2698     /* if this is not a parm push : ie. it is spill push 
2699     and spill push is always done on the local stack */
2700     if (!ic->parmPush) {
2701
2702         /* and the item is spilt then do nothing */
2703         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2704             return ;
2705
2706         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2707         size = AOP_SIZE(IC_LEFT(ic));
2708         /* push it on the stack */
2709         while(size--) {
2710             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2711             if (*l == '#') {
2712                 MOVA(l);
2713                 l = "acc";
2714             }
2715             pic16_emitcode("push","%s",l);
2716         }
2717         return ;        
2718     }
2719
2720     /* this is a paramter push: in this case we call
2721     the routine to find the call and save those
2722     registers that need to be saved */   
2723     saveRegisters(ic);
2724
2725     /* then do the push */
2726     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2727
2728
2729         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2730     size = AOP_SIZE(IC_LEFT(ic));
2731
2732     while (size--) {
2733         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2734         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2735             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2736             strcmp(l,"a") ) {
2737             pic16_emitcode("mov","a,%s",l);
2738             pic16_emitcode("push","acc");
2739         } else
2740             pic16_emitcode("push","%s",l);
2741     }       
2742
2743     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2744 #endif
2745 }
2746
2747 /*-----------------------------------------------------------------*/
2748 /* genIpop - recover the registers: can happen only for spilling   */
2749 /*-----------------------------------------------------------------*/
2750 static void genIpop (iCode *ic)
2751 {
2752   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2753 #if 0
2754     int size,offset ;
2755
2756
2757     /* if the temp was not pushed then */
2758     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2759         return ;
2760
2761     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2762     size = AOP_SIZE(IC_LEFT(ic));
2763     offset = (size-1);
2764     while (size--) 
2765         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2766                                    FALSE,TRUE));
2767
2768     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2769 #endif
2770 }
2771
2772 /*-----------------------------------------------------------------*/
2773 /* unsaverbank - restores the resgister bank from stack            */
2774 /*-----------------------------------------------------------------*/
2775 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2776 {
2777   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2778 #if 0
2779     int i;
2780     asmop *aop ;
2781     regs *r = NULL;
2782
2783     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2784     if (popPsw) {
2785         if (options.useXstack) {
2786             aop = newAsmop(0);
2787             r = getFreePtr(ic,&aop,FALSE);
2788             
2789             
2790             pic16_emitcode("mov","%s,_spx",r->name);
2791             pic16_emitcode("movx","a,@%s",r->name);
2792             pic16_emitcode("mov","psw,a");
2793             pic16_emitcode("dec","%s",r->name);
2794             
2795         }else
2796             pic16_emitcode ("pop","psw");
2797     }
2798
2799     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2800         if (options.useXstack) {       
2801             pic16_emitcode("movx","a,@%s",r->name);
2802             //pic16_emitcode("mov","(%s+%d),a",
2803             //       regspic16[i].base,8*bank+regspic16[i].offset);
2804             pic16_emitcode("dec","%s",r->name);
2805
2806         } else 
2807           pic16_emitcode("pop",""); //"(%s+%d)",
2808         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2809     }
2810
2811     if (options.useXstack) {
2812
2813         pic16_emitcode("mov","_spx,%s",r->name);
2814         pic16_freeAsmop(NULL,aop,ic,TRUE);
2815
2816     }
2817 #endif 
2818 }
2819
2820 /*-----------------------------------------------------------------*/
2821 /* saverbank - saves an entire register bank on the stack          */
2822 /*-----------------------------------------------------------------*/
2823 static void saverbank (int bank, iCode *ic, bool pushPsw)
2824 {
2825   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2826 #if 0
2827     int i;
2828     asmop *aop ;
2829     regs *r = NULL;
2830
2831     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2832     if (options.useXstack) {
2833
2834         aop = newAsmop(0);
2835         r = getFreePtr(ic,&aop,FALSE);  
2836         pic16_emitcode("mov","%s,_spx",r->name);
2837
2838     }
2839
2840     for (i = 0 ; i < pic16_nRegs ;i++) {
2841         if (options.useXstack) {
2842             pic16_emitcode("inc","%s",r->name);
2843             //pic16_emitcode("mov","a,(%s+%d)",
2844             //         regspic16[i].base,8*bank+regspic16[i].offset);
2845             pic16_emitcode("movx","@%s,a",r->name);           
2846         } else 
2847           pic16_emitcode("push","");// "(%s+%d)",
2848                      //regspic16[i].base,8*bank+regspic16[i].offset);
2849     }
2850     
2851     if (pushPsw) {
2852         if (options.useXstack) {
2853             pic16_emitcode("mov","a,psw");
2854             pic16_emitcode("movx","@%s,a",r->name);     
2855             pic16_emitcode("inc","%s",r->name);
2856             pic16_emitcode("mov","_spx,%s",r->name);       
2857             pic16_freeAsmop (NULL,aop,ic,TRUE);
2858             
2859         } else
2860             pic16_emitcode("push","psw");
2861         
2862         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2863     }
2864     ic->bankSaved = 1;
2865 #endif
2866 }
2867
2868
2869
2870 /*-----------------------------------------------------------------*/
2871 /* genCall - generates a call statement                            */
2872 /*-----------------------------------------------------------------*/
2873 static void genCall (iCode *ic)
2874 {
2875   sym_link *dtype;   
2876   int stackParms=0;
2877   
2878         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2879
2880         /* if caller saves & we have not saved then */
2881         if (!ic->regsSaved)
2882                 saveRegisters(ic);
2883
2884         /* if we are calling a function that is not using
2885          * the same register bank then we need to save the
2886          * destination registers on the stack */
2887         dtype = operandType(IC_LEFT(ic));
2888         if (currFunc && dtype && 
2889                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2890                 IFFUNC_ISISR(currFunc->type) &&
2891                 !ic->bankSaved) 
2892
2893                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2894
2895
2896         /* initialise stackParms for IPUSH pushes */
2897 //      stackParms = psuedoStkPtr;
2898 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
2899
2900         /* if send set is not empty the assign */
2901         if (_G.sendSet) {
2902           iCode *sic;
2903
2904                 /* For the Pic port, there is no data stack.
2905                  * So parameters passed to functions are stored
2906                  * in registers. (The pCode optimizer will get
2907                  * rid of most of these :). */
2908
2909           int psuedoStkPtr=-1; 
2910           int firstTimeThruLoop = 1;
2911
2912                 _G.sendSet = reverseSet(_G.sendSet);
2913
2914                 /* First figure how many parameters are getting passed */
2915                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2916                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2917                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2918                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2919                 }
2920
2921                 stackParms = psuedoStkPtr;
2922
2923                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2924                   int size, offset = 0;
2925
2926                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2927                         size = AOP_SIZE(IC_LEFT(sic));
2928
2929                         while (size--) {
2930                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2931                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2932                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2933
2934                                 if(!firstTimeThruLoop) {
2935                                         /* If this is not the first time we've been through the loop
2936                                          * then we need to save the parameter in a temporary
2937                                          * register. The last byte of the last parameter is
2938                                          * passed in W. */
2939
2940                                         pushw();
2941                                         --psuedoStkPtr;         // sanity check
2942                                 }
2943                         
2944                                 firstTimeThruLoop=0;
2945
2946                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2947                                 offset++;
2948                         }
2949                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2950                 }
2951                 _G.sendSet = NULL;
2952         }
2953
2954         /* make the call */
2955         pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2956                         OP_SYMBOL(IC_LEFT(ic))->rname :
2957                         OP_SYMBOL(IC_LEFT(ic))->name));
2958
2959         GpsuedoStkPtr=0;
2960         /* if we need assign a result value */
2961         if ((IS_ITEMP(IC_RESULT(ic)) && 
2962                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2963                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2964                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2965
2966                 _G.accInUse++;
2967                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2968                 _G.accInUse--;
2969
2970                 assignResultValue(IC_RESULT(ic), 1);
2971
2972                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2973                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2974                 
2975                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2976         }
2977
2978         if(!stackParms && ic->parmBytes) {
2979                 stackParms = ic->parmBytes;
2980         }
2981         
2982         if(stackParms>0) {
2983                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2984                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2985                 if(STACK_MODEL_LARGE) {
2986                         emitSKPNC;
2987                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2988                 }
2989         }
2990
2991         /* adjust the stack for parameters if required */
2992 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2993 #if 0
2994         if (ic->parmBytes) {
2995           int i;
2996
2997                 if (ic->parmBytes > 3) {
2998                         pic16_emitcode("mov","a,%s",spname);
2999                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3000                         pic16_emitcode("mov","%s,a",spname);
3001                 } else 
3002                         for ( i = 0 ; i <  ic->parmBytes ;i++)
3003                                 pic16_emitcode("dec","%s",spname);
3004         }
3005 #endif
3006
3007 #if 0
3008         /* if register bank was saved then pop them */
3009         if (ic->bankSaved)
3010                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3011
3012         /* if we hade saved some registers then unsave them */
3013         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3014                 unsaveRegisters (ic);
3015 #endif
3016 }
3017
3018
3019
3020 /*-----------------------------------------------------------------*/   // patch 14
3021 /* genPcall - generates a call by pointer statement                */
3022 /*-----------------------------------------------------------------*/
3023
3024 // new version, created from genCall
3025
3026 static void genPcall (iCode *ic)
3027 {
3028   sym_link *dtype;   
3029   int stackParms=0;
3030   symbol *retlbl = newiTempLabel(NULL);
3031   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3032   
3033         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3034
3035         /* if caller saves & we have not saved then */
3036         if (!ic->regsSaved)
3037                 saveRegisters(ic);
3038
3039         /* if we are calling a function that is not using
3040          * the same register bank then we need to save the
3041          * destination registers on the stack */
3042         dtype = operandType(IC_LEFT(ic));
3043         if (currFunc && dtype && 
3044                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
3045                 IFFUNC_ISISR(currFunc->type) &&
3046                 !ic->bankSaved) 
3047
3048                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3049
3050         /* if send set is not empty the assign */
3051         if (_G.sendSet) {
3052           iCode *sic;
3053
3054                 /* For the Pic port, there is no data stack.
3055                  * So parameters passed to functions are stored
3056                  * in registers. (The pCode optimizer will get
3057                  * rid of most of these :). */
3058
3059           int psuedoStkPtr=-1; 
3060           int firstTimeThruLoop = 1;
3061
3062                 _G.sendSet = reverseSet(_G.sendSet);
3063
3064                 /* First figure how many parameters are getting passed */
3065                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3066                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3067                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
3068                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
3069                 }
3070
3071                 stackParms = psuedoStkPtr;
3072
3073                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3074                   int size, offset = 0;
3075
3076                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3077                         size = AOP_SIZE(IC_LEFT(sic));
3078
3079                         while (size--) {
3080                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3081                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3082                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3083
3084                                 if(!firstTimeThruLoop) {
3085                                         /* If this is not the first time we've been through the loop
3086                                          * then we need to save the parameter in a temporary
3087                                          * register. The last byte of the last parameter is
3088                                          * passed in W. */
3089
3090                                         pushw();
3091                                         --psuedoStkPtr;         // sanity check
3092                                 }
3093                         
3094                                 firstTimeThruLoop=0;
3095
3096                                 mov2w (AOP(IC_LEFT(sic)),  offset);
3097                                 offset++;
3098                         }
3099                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3100                 }
3101                 _G.sendSet = NULL;
3102         }
3103
3104         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3105
3106         // push return address
3107         // push $ on return stack, then replace with retlbl
3108
3109         pic16_emitpcodeNULLop(POC_PUSH);
3110
3111         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3112         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3113         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3114         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3115         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3116         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3117
3118         /* make the call by writing the pointer into pc */
3119         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3120         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3121
3122         // note: MOVFF to PCL not allowed
3123         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3124         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3125
3126
3127 //      pic16_emitpcode(POC_GOTO, pic16_popGetLabel(retlbl->key));
3128 //      pic16_emitpcodeNULLop(POC_NOP);
3129 //      pic16_emitpcodeNULLop(POC_NOP);
3130
3131         /* return address is here: (X) */
3132         pic16_emitpLabelFORCE(retlbl->key);
3133
3134 //      pic16_emitpcodeNULLop(POC_NOP);
3135
3136         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3137
3138         GpsuedoStkPtr=0;
3139         /* if we need assign a result value */
3140         if ((IS_ITEMP(IC_RESULT(ic)) && 
3141                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3142                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
3143                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3144
3145                 _G.accInUse++;
3146                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3147                 _G.accInUse--;
3148
3149                 assignResultValue(IC_RESULT(ic), 1);
3150
3151                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3152                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3153                 
3154                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3155         }
3156
3157         if(stackParms>0) {
3158                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3159                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3160                 if(STACK_MODEL_LARGE) {
3161                         emitSKPNC;
3162                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3163                 }
3164         }
3165
3166         /* adjust the stack for parameters if required */
3167 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3168
3169         if (ic->parmBytes) {
3170           int i;
3171
3172                 if (ic->parmBytes > 3) {
3173                         pic16_emitcode("mov","a,%s",spname);
3174                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3175                         pic16_emitcode("mov","%s,a",spname);
3176                 } else 
3177                         for ( i = 0 ; i <  ic->parmBytes ;i++)
3178                                 pic16_emitcode("dec","%s",spname);
3179         }
3180
3181         /* if register bank was saved then pop them */
3182         if (ic->bankSaved)
3183                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3184
3185         /* if we hade saved some registers then unsave them */
3186         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3187                 unsaveRegisters (ic);
3188 }
3189
3190
3191 #if 0                                                                           // patch 14
3192 // old version, kept for reference
3193
3194 /*-----------------------------------------------------------------*/
3195 /* genPcall - generates a call by pointer statement                */
3196 /*-----------------------------------------------------------------*/
3197 static void genPcall (iCode *ic)
3198 {
3199     sym_link *dtype;
3200     symbol *rlbl = newiTempLabel(NULL);
3201
3202
3203     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3204     /* if caller saves & we have not saved then */
3205     if (!ic->regsSaved)
3206         saveRegisters(ic);
3207
3208     /* if we are calling a function that is not using
3209     the same register bank then we need to save the
3210     destination registers on the stack */
3211     dtype = operandType(IC_LEFT(ic));
3212     if (currFunc && dtype && 
3213         IFFUNC_ISISR(currFunc->type) &&
3214         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3215         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3216
3217
3218     /* push the return address on to the stack */
3219     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3220     pic16_emitcode("push","acc");    
3221     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3222     pic16_emitcode("push","acc");
3223     
3224     if (options.model == MODEL_FLAT24)
3225     {
3226         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3227         pic16_emitcode("push","acc");    
3228     }
3229
3230     /* now push the calling address */
3231     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3232
3233     pushSide(IC_LEFT(ic), FPTRSIZE);
3234
3235     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
3236
3237     /* if send set is not empty the assign */
3238     if (_G.sendSet) {
3239         iCode *sic ;
3240
3241         for (sic = setFirstItem(_G.sendSet) ; sic ; 
3242              sic = setNextItem(_G.sendSet)) {
3243             int size, offset = 0;
3244             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3245             size = AOP_SIZE(IC_LEFT(sic));
3246             while (size--) {
3247                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3248                                 FALSE,FALSE);
3249                 if (strcmp(l,fReturn[offset]))
3250                     pic16_emitcode("mov","%s,%s",
3251                              fReturn[offset],
3252                              l);
3253                 offset++;
3254             }
3255             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3256         }
3257         _G.sendSet = NULL;
3258     }
3259
3260     pic16_emitcode("ret","");
3261     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3262
3263
3264     /* if we need assign a result value */
3265     if ((IS_ITEMP(IC_RESULT(ic)) &&
3266          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3267           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3268         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3269
3270         _G.accInUse++;
3271         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3272         _G.accInUse--;
3273         
3274         assignResultValue(IC_RESULT(ic), 1);
3275
3276         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3277     }
3278
3279     /* adjust the stack for parameters if 
3280     required */
3281     if (ic->parmBytes) {
3282         int i;
3283         if (ic->parmBytes > 3) {
3284             pic16_emitcode("mov","a,%s",spname);
3285             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3286             pic16_emitcode("mov","%s,a",spname);
3287         } else 
3288             for ( i = 0 ; i <  ic->parmBytes ;i++)
3289                 pic16_emitcode("dec","%s",spname);
3290
3291     }
3292
3293     /* if register bank was saved then unsave them */
3294     if (currFunc && dtype && 
3295         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3296         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3297
3298     /* if we hade saved some registers then
3299     unsave them */
3300     if (ic->regsSaved)
3301         unsaveRegisters (ic);
3302
3303 }
3304 #endif                                                                          // patch 14
3305
3306
3307 /*-----------------------------------------------------------------*/
3308 /* resultRemat - result  is rematerializable                       */
3309 /*-----------------------------------------------------------------*/
3310 static int resultRemat (iCode *ic)
3311 {
3312   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3313   if (SKIP_IC(ic) || ic->op == IFX)
3314     return 0;
3315
3316   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3317     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3318     if (sym->remat && !POINTER_SET(ic)) 
3319       return 1;
3320   }
3321
3322   return 0;
3323 }
3324
3325 #if defined(__BORLANDC__) || defined(_MSC_VER)
3326 #define STRCASECMP stricmp
3327 #else
3328 #define STRCASECMP strcasecmp
3329 #endif
3330
3331 #if 0
3332 /*-----------------------------------------------------------------*/
3333 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3334 /*-----------------------------------------------------------------*/
3335 static bool inExcludeList(char *s)
3336 {
3337   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3338     int i =0;
3339     
3340     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3341     if (options.excludeRegs[i] &&
3342     STRCASECMP(options.excludeRegs[i],"none") == 0)
3343         return FALSE ;
3344
3345     for ( i = 0 ; options.excludeRegs[i]; i++) {
3346         if (options.excludeRegs[i] &&
3347         STRCASECMP(s,options.excludeRegs[i]) == 0)
3348             return TRUE;
3349     }
3350     return FALSE ;
3351 }
3352 #endif
3353
3354 /*-----------------------------------------------------------------*/
3355 /* genFunction - generated code for function entry                 */
3356 /*-----------------------------------------------------------------*/
3357 static void genFunction (iCode *ic)
3358 {
3359   symbol *sym;
3360   sym_link *ftype;
3361   
3362         DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3363
3364         pic16_labelOffset += (max_key+4);
3365         max_key=0;
3366         GpsuedoStkPtr=0;
3367         _G.nRegsSaved = 0;
3368
3369         ftype = operandType(IC_LEFT(ic));
3370         sym = OP_SYMBOL(IC_LEFT(ic));
3371
3372         if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3373                 /* create an absolute section at the interrupt vector:
3374                  * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3375           symbol *asym;
3376           char asymname[128];
3377           pBlock *apb;
3378
3379                 {
3380                   int i, found=-1;
3381
3382                         sym = OP_SYMBOL( IC_LEFT(ic));
3383                         for(i=0;i<=2;i++) {
3384                                 if(interrupts[i]->name
3385                                         && !STRCASECMP(interrupts[i]->name, sym->name)) {
3386                                         found = i;
3387                                         break;
3388                                 }
3389                         }
3390                         
3391                         if(found == -1) {
3392                                 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3393                                         __FILE__, __LINE__, sym->name);
3394                                 assert( 0 );
3395                         }
3396                         _G.interruptvector = found;
3397                 }
3398
3399                 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3400                 asym = newSymbol(asymname, 0);
3401
3402                 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3403                 pic16_addpBlock( apb );
3404
3405                 pic16_addpCode2pBlock(apb,
3406                         pic16_newpCodeCharP(";-----------------------------------------"));
3407
3408
3409                 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3410
3411                 pic16_addpCode2pBlock(apb,
3412                         pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3413                 
3414                 /* mark the end of this tiny function */
3415                 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3416
3417                 {
3418                   absSym *abSym;
3419
3420                         abSym = Safe_calloc(1, sizeof(absSym));
3421                         abSym->name = Safe_strdup( asymname );
3422
3423                         switch( _G.interruptvector ) {
3424                                 case 0: abSym->address = 0x000000; break;
3425                                 case 1: abSym->address = 0x000008; break;
3426                                 case 2: abSym->address = 0x000018; break;
3427                         }
3428
3429                         /* relocate interrupt vectors if needed */
3430                         abSym->address += pic16_options.ivt_loc;
3431
3432                         addSet(&absSymSet, abSym);
3433                 }
3434         }
3435
3436
3437         /* create the function header */
3438         pic16_emitcode(";","-----------------------------------------");
3439         pic16_emitcode(";"," function %s",sym->name);
3440         pic16_emitcode(";","-----------------------------------------");
3441
3442         pic16_emitcode("","%s:",sym->rname);
3443         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3444
3445
3446         {
3447           absSym *ab;
3448
3449                 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3450                         if(!strcmp(ab->name, sym->name)) {
3451                                 pic16_pBlockConvert2Absolute(pb);
3452                                 break;
3453                         }
3454
3455         }
3456
3457
3458         if(IFFUNC_ISNAKED(ftype)) {
3459                 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3460                 return;
3461         }
3462         
3463         /* if critical function then turn interrupts off */
3464         if (IFFUNC_ISCRITICAL(ftype))
3465                 pic16_emitcode("clr","ea");
3466
3467         /* if this is an interrupt service routine then
3468          * save acc, b, dpl, dph  */
3469         if (IFFUNC_ISISR(sym->type)) {
3470           int i;
3471
3472                 _G.usefastretfie = 1;   /* use shadow registers by default */
3473                 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3474                 if(!(_G.interruptvector == 1)) {
3475
3476                         /* do not save WREG,STATUS,BSR for high priority interrupts
3477                          * because they are stored in the hardware shadow registers already */
3478                         _G.usefastretfie = 0;
3479                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3480                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3481                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3482                 }
3483
3484
3485                 /* these should really be optimized somehow, because not all
3486                  * interrupt handlers modify them */
3487                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3488                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3489                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3490                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3491
3492 //                pic16_pBlockConvert2ISR(pb);
3493                 
3494                 /* if any registers used */
3495                 if (sym->regsUsed) {
3496                         /* save the registers used */
3497                         DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3498                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3499                                 if (bitVectBitValue(sym->regsUsed,i)) {
3500 #if 0
3501                                         fprintf(stderr, "%s:%d function %s uses register %s\n",
3502                                                         __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3503                                                         pic16_regWithIdx(i)->name);
3504 #endif
3505
3506                                         pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3507                                         _G.nRegsSaved++;
3508
3509                                         if(!pic16_regWithIdx(i)->wasUsed) {
3510                                                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3511                                                         __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3512
3513                                                 pic16_regWithIdx(i)->wasUsed = 1;
3514                                         }
3515                                 }
3516                         }
3517                 }
3518         } else {
3519                 /* emit code to setup stack frame if user enabled,
3520                  * and function is not main() */
3521          
3522 //              fprintf(stderr, "function name: %s\n", sym->name);
3523                 if(strcmp(sym->name, "main")) {
3524                         if(/*!options.ommitFramePtr || */sym->regsUsed) {
3525                         /* setup the stack frame */
3526                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3527                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3528                                 if(STACK_MODEL_LARGE)
3529                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3530                         }
3531                 }
3532
3533                 /* if callee-save to be used for this function
3534                 * then save the registers being used in this function */
3535 //              if (IFFUNC_CALLEESAVES(sym->type))
3536                 {
3537                   int i;
3538
3539 //                      fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3540
3541 //                      pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3542
3543                         /* if any registers used */
3544                         if (sym->regsUsed) {
3545                                 /* save the registers used */
3546                                 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3547                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3548                                         if (bitVectBitValue(sym->regsUsed,i)) {
3549
3550 #if 0
3551                                                 fprintf(stderr, "%s:%d function %s uses register %s (wasUsed: %d, %p)\n",
3552                                                                 __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3553                                                                 pic16_regWithIdx(i)->name,
3554                                                                 pic16_regWithIdx(i)->wasUsed,
3555                                                                 pic16_regWithIdx(i));
3556 #endif
3557
3558                                                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3559
3560 //                                              pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3561 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3562 //                                                      &pic16_pc_postdec1, 0));
3563
3564                                                 _G.nRegsSaved++;
3565
3566                                                 if(!pic16_regWithIdx(i)->wasUsed) {
3567                                                         fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3568                                                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3569
3570                                                         pic16_regWithIdx(i)->wasUsed = 1;
3571                                                 }
3572                                         
3573                                         }
3574                                 }
3575                         }
3576                 }
3577         }
3578
3579
3580         
3581 #if 0
3582         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3583
3584                 if (options.useXstack) {
3585                         pic16_emitcode("mov","r0,%s",spname);
3586                         pic16_emitcode("mov","a,_bp");
3587                         pic16_emitcode("movx","@r0,a");
3588                         pic16_emitcode("inc","%s",spname);
3589                 } else {
3590                         /* set up the stack */
3591                         pic16_emitcode ("push","_bp");     /* save the callers stack  */
3592                 }
3593                 pic16_emitcode ("mov","_bp,%s",spname);
3594         }
3595 #endif
3596         DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3597
3598         /* adjust the stack for the function */
3599         if (sym->stack) {
3600           int i = sym->stack;
3601
3602                 if (i > 127 ) 
3603                         werror(W_STACK_OVERFLOW,sym->name);
3604
3605                 if (i > 3 && sym->recvSize < 4) {              
3606                         pic16_emitcode ("mov","a,sp");
3607                         pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3608                         pic16_emitcode ("mov","sp,a");
3609                 } else
3610                         while(i--)
3611                                 pic16_emitcode("inc","sp");
3612         }
3613
3614         if (sym->xstack) {
3615                 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3616
3617                 pic16_emitcode ("mov","a,_spx");
3618                 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3619                 pic16_emitcode ("mov","_spx,a");
3620         }
3621     
3622 }
3623
3624 /*-----------------------------------------------------------------*/
3625 /* genEndFunction - generates epilogue for functions               */
3626 /*-----------------------------------------------------------------*/
3627 static void genEndFunction (iCode *ic)
3628 {
3629     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3630
3631     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3632
3633     if(IFFUNC_ISNAKED(sym->type)) {
3634         DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3635         return;
3636     }
3637
3638     /* add code for ISCRITICAL */
3639
3640 #if 0
3641     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3642     {
3643         pic16_emitcode ("mov","%s,_bp",spname);
3644     }
3645 #endif
3646
3647     /* if use external stack but some variables were
3648     added to the local stack then decrement the
3649     local stack */
3650     if (options.useXstack && sym->stack) {      
3651         pic16_emitcode("mov","a,sp");
3652         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3653         pic16_emitcode("mov","sp,a");
3654     }
3655
3656
3657 #if 0
3658     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3659         if (options.useXstack) {
3660             pic16_emitcode("mov","r0,%s",spname);
3661             pic16_emitcode("movx","a,@r0");
3662             pic16_emitcode("mov","_bp,a");
3663             pic16_emitcode("dec","%s",spname);
3664         }
3665         else
3666         {
3667             pic16_emitcode ("pop","_bp");
3668         }
3669     }
3670 #endif
3671
3672         if (IFFUNC_ISISR(sym->type)) {
3673                 /* now we need to restore the registers */
3674                 /* if any registers used */
3675                 if (sym->regsUsed) {
3676                   int i;
3677
3678                         /* restore registers used */
3679                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3680                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3681                                 if (bitVectBitValue(sym->regsUsed,i)) {
3682
3683 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3684 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3685 //                                                      pic16_regWithIdx(i)->name);
3686
3687                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3688
3689 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3690 //                                                      &pic16_pc_preinc1,
3691 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3692
3693                                 }
3694                         }
3695                 }
3696         
3697                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3698                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3699                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3700                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3701
3702                 if(!(_G.interruptvector == 1)) {
3703                         /* do not restore interrupt vector for WREG,STATUS,BSR
3704                          * for high priority interrupt, see genFunction */
3705                          
3706                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3707                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3708                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3709                 }
3710         
3711                 _G.interruptvector = 0;         /* sanity check */
3712
3713 //              pic16_pBlockConvert2ISR(pb);
3714
3715
3716                 /* if debug then send end of function */
3717 /*      if (options.debug && currFunc)  */
3718                 if (currFunc) {
3719                         debugFile->writeEndFunction (currFunc, ic, 1);
3720                 }
3721         
3722                 if(_G.usefastretfie)
3723                         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3724                 else
3725                 pic16_emitpcodeNULLop(POC_RETFIE);
3726                 _G.usefastretfie = 0;
3727         } else {
3728                 if (IFFUNC_ISCRITICAL(sym->type))
3729                         pic16_emitcode("setb","ea");
3730         
3731
3732 //              pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3733
3734                 /* if any registers used */
3735                 if (sym->regsUsed) {
3736                   int i;
3737                         /* save the registers used */
3738                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3739                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3740                                 if (bitVectBitValue(sym->regsUsed,i)) {
3741         
3742 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3743 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3744 //                                                      pic16_regWithIdx(i)->name);
3745         
3746                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3747                                         
3748 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3749 //                                              &pic16_pc_preinc1,
3750 //                                              PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3751
3752                                         _G.nRegsSaved--;
3753                                 }
3754                         }
3755                 }
3756         
3757 //              pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3758                 /* if debug then send end of function */
3759                 if (currFunc) {
3760                         debugFile->writeEndFunction (currFunc, ic, 1);
3761                 }
3762
3763                 /* insert code to restore stack frame, if user enabled it
3764                  * and function is not main() */
3765          
3766
3767                 if(strcmp(sym->name, "main")) {
3768                         if(/*!options.ommitFramePtr ||*/ sym->regsUsed) {
3769                                 /* restore stack frame */
3770                                 if(STACK_MODEL_LARGE)
3771                                         pic16_emitpcode(POC_MOVFF,
3772                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3773                                 pic16_emitpcode(POC_MOVFF,
3774                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3775                         }
3776                 }
3777
3778                 pic16_emitpcodeNULLop(POC_RETURN);
3779
3780                 /* Mark the end of a function */
3781                 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3782         }
3783
3784 }
3785
3786
3787 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3788 {
3789
3790         if(is_LitOp(op)) {
3791                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3792
3793                 if(dest->type != PO_WREG)
3794                         pic16_emitpcode(POC_MOVWF, dest);
3795         } else {
3796                 if(dest->type == PO_WREG && (offset == 0)) {
3797                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3798                         return;
3799                 }
3800                 
3801                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3802                         pic16_popGet(AOP(op), offset), dest));
3803         }
3804 }
3805
3806 /*-----------------------------------------------------------------*/
3807 /* genRet - generate code for return statement                     */
3808 /*-----------------------------------------------------------------*/
3809 static void genRet (iCode *ic)
3810 {
3811   int size;
3812   operand *left;
3813
3814         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3815         /* if we have no return value then
3816          * just generate the "ret" */
3817         
3818         if (!IC_LEFT(ic)) 
3819                 goto jumpret;       
3820     
3821         /* we have something to return then
3822          * move the return value into place */
3823         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3824         size = AOP_SIZE(IC_LEFT(ic));
3825
3826         if(size <= 4) {
3827                 if(size>3) {
3828                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3829 //                      pic16_emitpcode(POC_MOVFF,
3830 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3831                 }
3832                 if(size>2) {
3833                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3834 //                      pic16_emitpcode(POC_MOVFF,
3835 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3836                 }
3837                 if(size>1) {
3838                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3839 //                      pic16_emitpcode(POC_MOVFF,
3840 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3841                 }
3842
3843 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3844
3845                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3846 //              pic16_emitpcode(POC_MOVFF,
3847 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3848
3849         } else {
3850                 /* >32-bits, setup stack and FSR0 */
3851                 while (size--) {
3852 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3853 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3854
3855                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3856
3857 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3858                         GpsuedoStkPtr++;
3859                 }
3860                         
3861                 /* setup FSR0 */
3862                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3863                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3864
3865                 if(STACK_MODEL_LARGE) {
3866                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3867                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3868                 } else {
3869                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3870                 }
3871         }
3872                                 
3873 #if 0
3874         /* old code, left here for reference -- VR */    
3875         while (size--) {
3876           char *l ;
3877
3878                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3879                         /* #NOCHANGE */
3880                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3881                         pic16_emitpcomment("push %s",l);
3882                         pushed++;
3883                 } else {
3884                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3885                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3886                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3887                         
3888                         if (strcmp(fReturn[offset],l)) {
3889                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3890                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3891                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3892                                 } else {
3893                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3894                                 }
3895                                 
3896                                 if(size) {
3897                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3898                                 }
3899                                 offset++;
3900                         }
3901                 }
3902         }    
3903
3904         if (pushed) {
3905                 while(pushed) {
3906                         pushed--;
3907                         if (strcmp(fReturn[pushed],"a"))
3908                                 pic16_emitcode("pop",fReturn[pushed]);
3909                         else
3910                                 pic16_emitcode("pop","acc");
3911                 }
3912         }
3913 #endif
3914
3915
3916         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3917     
3918 jumpret:
3919         /* generate a jump to the return label
3920          * if the next is not the return statement */
3921         if (!(ic->next && ic->next->op == LABEL
3922                 && IC_LABEL(ic->next) == returnLabel)) {
3923         
3924                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3925                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3926         }
3927 }
3928
3929 /*-----------------------------------------------------------------*/
3930 /* genLabel - generates a label                                    */
3931 /*-----------------------------------------------------------------*/
3932 static void genLabel (iCode *ic)
3933 {
3934
3935
3936     /* special case never generate */
3937     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3938     if (IC_LABEL(ic) == entryLabel)
3939         return ;
3940
3941     pic16_emitpLabel(IC_LABEL(ic)->key);
3942     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3943 }
3944
3945 /*-----------------------------------------------------------------*/
3946 /* genGoto - generates a goto                                      */
3947 /*-----------------------------------------------------------------*/
3948 //tsd
3949 static void genGoto (iCode *ic)
3950 {
3951   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3952   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3953 }
3954
3955
3956 /*-----------------------------------------------------------------*/
3957 /* genMultbits :- multiplication of bits                           */
3958 /*-----------------------------------------------------------------*/
3959 static void genMultbits (operand *left, 
3960                          operand *right, 
3961                          operand *result)
3962 {
3963   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3964
3965   if(!pic16_sameRegs(AOP(result),AOP(right)))
3966     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3967
3968   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3969   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3970   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3971
3972 }
3973
3974
3975 /*-----------------------------------------------------------------*/
3976 /* genMultOneByte : 8 bit multiplication & division                */
3977 /*-----------------------------------------------------------------*/
3978 static void genMultOneByte (operand *left,
3979                             operand *right,
3980                             operand *result)
3981 {
3982
3983   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3984   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3985   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3986
3987   /* (if two literals, the value is computed before) */
3988   /* if one literal, literal on the right */
3989   if (AOP_TYPE(left) == AOP_LIT){
3990     operand *t = right;
3991     right = left;
3992     left = t;
3993   }
3994
3995         /* size is already checked in genMult == 1 */
3996 //      size = AOP_SIZE(result);
3997
3998         if (AOP_TYPE(right) == AOP_LIT){
3999                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4000                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4001                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4002                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4003         } else {
4004                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4005                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4006                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4007                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4008         }
4009         
4010         pic16_genMult8X8_8 (left, right,result);
4011 }
4012
4013 /*-----------------------------------------------------------------*/
4014 /* genMultOneWord : 16 bit multiplication                          */
4015 /*-----------------------------------------------------------------*/
4016 static void genMultOneWord (operand *left,
4017                             operand *right,
4018                             operand *result)
4019 {
4020
4021         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4022         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4023         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4024
4025         /* (if two literals, the value is computed before)
4026          * if one literal, literal on the right */
4027         if (AOP_TYPE(left) == AOP_LIT){
4028           operand *t = right;
4029                 right = left;
4030                 left = t;
4031         }
4032
4033         /* size is checked already == 2 */
4034 //      size = AOP_SIZE(result);
4035
4036         if (AOP_TYPE(right) == AOP_LIT) {
4037                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4038                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4039                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4040                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4041         } else {
4042                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4043                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4044                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4045                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4046         }
4047         
4048         pic16_genMult16X16_16(left, right,result);
4049 }
4050
4051 /*-----------------------------------------------------------------*/
4052 /* genMultOneLong : 32 bit multiplication                          */
4053 /*-----------------------------------------------------------------*/
4054 static void genMultOneLong (operand *left,
4055                             operand *right,
4056                             operand *result)
4057 {
4058
4059         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4060         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4061         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4062
4063         /* (if two literals, the value is computed before)
4064          * if one literal, literal on the right */
4065         if (AOP_TYPE(left) == AOP_LIT){
4066           operand *t = right;
4067                 right = left;
4068                 left = t;
4069         }
4070
4071         /* size is checked already == 4 */
4072 //      size = AOP_SIZE(result);
4073
4074         if (AOP_TYPE(right) == AOP_LIT) {
4075                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4076                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4077                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4078                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4079         } else {
4080                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4081                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4082                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4083                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4084         }
4085         
4086         pic16_genMult32X32_32(left, right,result);
4087 }
4088
4089
4090
4091 /*-----------------------------------------------------------------*/
4092 /* genMult - generates code for multiplication                     */
4093 /*-----------------------------------------------------------------*/
4094 static void genMult (iCode *ic)
4095 {
4096   operand *left = IC_LEFT(ic);
4097   operand *right = IC_RIGHT(ic);
4098   operand *result= IC_RESULT(ic);   
4099
4100         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4101         /* assign the amsops */
4102         pic16_aopOp (left,ic,FALSE);
4103         pic16_aopOp (right,ic,FALSE);
4104         pic16_aopOp (result,ic,TRUE);
4105
4106         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4107
4108         /* special cases first *
4109         * both are bits */
4110         if (AOP_TYPE(left) == AOP_CRY
4111                 && AOP_TYPE(right)== AOP_CRY) {
4112                 genMultbits(left,right,result);
4113           goto release ;
4114         }
4115
4116         /* if both are of size == 1 */
4117         if(AOP_SIZE(left) == 1
4118                 && AOP_SIZE(right) == 1) {
4119                 genMultOneByte(left,right,result);
4120           goto release ;
4121         }
4122
4123         /* if both are of size == 2 */
4124         if(AOP_SIZE(left) == 2
4125                 && AOP_SIZE(right) == 2) {
4126                 genMultOneWord(left, right, result);
4127           goto release;
4128         }
4129         
4130         /* if both are of size == 4 */
4131         if(AOP_SIZE(left) == 4
4132                 && AOP_SIZE(right) == 4) {
4133                 genMultOneLong(left, right, result);
4134           goto release;
4135         }
4136         
4137         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4138
4139
4140         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4141         /* should have been converted to function call */
4142         assert(0) ;
4143
4144 release :
4145         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4146         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4147         pic16_freeAsmop(result,NULL,ic,TRUE); 
4148 }
4149
4150 /*-----------------------------------------------------------------*/
4151 /* genDivbits :- division of bits                                  */
4152 /*-----------------------------------------------------------------*/
4153 static void genDivbits (operand *left, 
4154                         operand *right, 
4155                         operand *result)
4156 {
4157
4158     char *l;
4159
4160     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4161     /* the result must be bit */    
4162     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4163     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4164
4165     MOVA(l);    
4166
4167     pic16_emitcode("div","ab");
4168     pic16_emitcode("rrc","a");
4169     pic16_aopPut(AOP(result),"c",0);
4170 }
4171
4172 /*-----------------------------------------------------------------*/
4173 /* genDivOneByte : 8 bit division                                  */
4174 /*-----------------------------------------------------------------*/
4175 static void genDivOneByte (operand *left,
4176                            operand *right,
4177                            operand *result)
4178 {
4179     sym_link *opetype = operandType(result);
4180     char *l ;
4181     symbol *lbl ;
4182     int size,offset;
4183
4184         /* result = divident / divisor
4185          * - divident may be a register or a literal,
4186          * - divisor may be a register or a literal,
4187          * so there are 3 cases (literal / literal is optimized
4188          * by the front-end) to handle.
4189          * In addition we must handle signed and unsigned, which
4190          * result in 6 final different cases -- VR */
4191
4192     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4193     size = AOP_SIZE(result) - 1;
4194     offset = 1;
4195     /* signed or unsigned */
4196     if (SPEC_USIGN(opetype)) {
4197       pCodeOp *pct1,    /* count */
4198                 *pct2,  /* reste */
4199                 *pct3;  /* temp */
4200       symbol *label1, *label2, *label3;;
4201
4202
4203         /* unsigned is easy */
4204
4205         pct1 = pic16_popGetTempReg();
4206         pct2 = pic16_popGetTempReg();
4207         pct3 = pic16_popGetTempReg();
4208         
4209         label1 = newiTempLabel(NULL);
4210         label2 = newiTempLabel(NULL);
4211         label3 = newiTempLabel(NULL);
4212
4213         /* the following algorithm is extracted from divuint.c */
4214
4215         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4216         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4217         
4218         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4219
4220         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4221         
4222         pic16_emitpLabel(label1->key);
4223         
4224         emitCLRC;
4225         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4226
4227
4228         emitCLRC;
4229         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4230         
4231
4232         emitSKPNC;
4233         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4234         
4235         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4236         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4237         
4238         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4239         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4240         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4241         
4242         pic16_emitpLabel( label3->key );
4243         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4244         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4245         
4246         
4247
4248         pic16_emitpLabel(label2->key);
4249         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4250         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4251         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4252         
4253         /* result is in wreg */
4254         if(AOP_TYPE(result) != AOP_ACC)
4255                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4256
4257         pic16_popReleaseTempReg( pct3 );
4258         pic16_popReleaseTempReg( pct2 );
4259         pic16_popReleaseTempReg( pct1 );
4260
4261         return ;
4262     }
4263
4264     /* signed is a little bit more difficult */
4265
4266     /* save the signs of the operands */
4267     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4268     MOVA(l);    
4269     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4270     pic16_emitcode("push","acc"); /* save it on the stack */
4271
4272     /* now sign adjust for both left & right */
4273     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4274     MOVA(l);       
4275     lbl = newiTempLabel(NULL);
4276     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4277     pic16_emitcode("cpl","a");   
4278     pic16_emitcode("inc","a");
4279     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4280     pic16_emitcode("mov","b,a");
4281
4282     /* sign adjust left side */
4283     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4284     MOVA(l);
4285
4286     lbl = newiTempLabel(NULL);
4287     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4288     pic16_emitcode("cpl","a");
4289     pic16_emitcode("inc","a");
4290     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4291
4292     /* now the division */
4293     pic16_emitcode("div","ab");
4294     /* we are interested in the lower order
4295     only */
4296     pic16_emitcode("mov","b,a");
4297     lbl = newiTempLabel(NULL);
4298     pic16_emitcode("pop","acc");   
4299     /* if there was an over flow we don't 
4300     adjust the sign of the result */
4301     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4302     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4303     CLRC;
4304     pic16_emitcode("clr","a");
4305     pic16_emitcode("subb","a,b");
4306     pic16_emitcode("mov","b,a");
4307     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4308
4309     /* now we are done */
4310     pic16_aopPut(AOP(result),"b",0);
4311     if(size > 0){
4312         pic16_emitcode("mov","c,b.7");
4313         pic16_emitcode("subb","a,acc");   
4314     }
4315     while (size--)
4316         pic16_aopPut(AOP(result),"a",offset++);
4317
4318 }
4319
4320 /*-----------------------------------------------------------------*/
4321 /* genDiv - generates code for division                            */
4322 /*-----------------------------------------------------------------*/
4323 static void genDiv (iCode *ic)
4324 {
4325     operand *left = IC_LEFT(ic);
4326     operand *right = IC_RIGHT(ic);
4327     operand *result= IC_RESULT(ic);   
4328
4329
4330         /* Division is a very lengthy algorithm, so it is better
4331          * to call support routines than inlining algorithm.
4332          * Division functions written here just in case someone
4333          * wants to inline and not use the support libraries -- VR */
4334
4335     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4336     /* assign the amsops */
4337     pic16_aopOp (left,ic,FALSE);
4338     pic16_aopOp (right,ic,FALSE);
4339     pic16_aopOp (result,ic,TRUE);
4340
4341     /* special cases first */
4342     /* both are bits */
4343     if (AOP_TYPE(left) == AOP_CRY &&
4344         AOP_TYPE(right)== AOP_CRY) {
4345         genDivbits(left,right,result);
4346         goto release ;
4347     }
4348
4349     /* if both are of size == 1 */
4350     if (AOP_SIZE(left) == 1 &&
4351         AOP_SIZE(right) == 1 ) {
4352         genDivOneByte(left,right,result);
4353         goto release ;
4354     }
4355
4356     /* should have been converted to function call */
4357     assert(0);
4358 release :
4359     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4360     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4361     pic16_freeAsmop(result,NULL,ic,TRUE); 
4362 }
4363
4364 /*-----------------------------------------------------------------*/
4365 /* genModbits :- modulus of bits                                   */
4366 /*-----------------------------------------------------------------*/
4367 static void genModbits (operand *left, 
4368                         operand *right, 
4369                         operand *result)
4370 {
4371
4372     char *l;
4373
4374     /* the result must be bit */    
4375     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4376     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4377
4378     MOVA(l);       
4379
4380     pic16_emitcode("div","ab");
4381     pic16_emitcode("mov","a,b");
4382     pic16_emitcode("rrc","a");
4383     pic16_aopPut(AOP(result),"c",0);
4384 }
4385
4386 /*-----------------------------------------------------------------*/
4387 /* genModOneByte : 8 bit modulus                                   */
4388 /*-----------------------------------------------------------------*/
4389 static void genModOneByte (operand *left,
4390                            operand *right,
4391                            operand *result)
4392 {
4393     sym_link *opetype = operandType(result);
4394     char *l ;
4395     symbol *lbl ;
4396
4397     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4398     /* signed or unsigned */
4399     if (SPEC_USIGN(opetype)) {
4400         /* unsigned is easy */
4401         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4402         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4403         MOVA(l);    
4404         pic16_emitcode("div","ab");
4405         pic16_aopPut(AOP(result),"b",0);
4406         return ;
4407     }
4408
4409     /* signed is a little bit more difficult */
4410
4411     /* save the signs of the operands */
4412     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4413     MOVA(l);
4414
4415     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4416     pic16_emitcode("push","acc"); /* save it on the stack */
4417
4418     /* now sign adjust for both left & right */
4419     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4420     MOVA(l);
4421
4422     lbl = newiTempLabel(NULL);
4423     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4424     pic16_emitcode("cpl","a");   
4425     pic16_emitcode("inc","a");
4426     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4427     pic16_emitcode("mov","b,a"); 
4428
4429     /* sign adjust left side */
4430     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4431     MOVA(l);
4432
4433     lbl = newiTempLabel(NULL);
4434     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4435     pic16_emitcode("cpl","a");   
4436     pic16_emitcode("inc","a");
4437     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4438
4439     /* now the multiplication */
4440     pic16_emitcode("div","ab");
4441     /* we are interested in the lower order
4442     only */
4443     lbl = newiTempLabel(NULL);
4444     pic16_emitcode("pop","acc");   
4445     /* if there was an over flow we don't 
4446     adjust the sign of the result */
4447     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4448     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4449     CLRC ;
4450     pic16_emitcode("clr","a");
4451     pic16_emitcode("subb","a,b");
4452     pic16_emitcode("mov","b,a");
4453     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4454
4455     /* now we are done */
4456     pic16_aopPut(AOP(result),"b",0);
4457
4458 }
4459
4460 /*-----------------------------------------------------------------*/
4461 /* genMod - generates code for division                            */
4462 /*-----------------------------------------------------------------*/
4463 static void genMod (iCode *ic)
4464 {
4465     operand *left = IC_LEFT(ic);
4466     operand *right = IC_RIGHT(ic);
4467     operand *result= IC_RESULT(ic);  
4468
4469     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4470     /* assign the amsops */
4471     pic16_aopOp (left,ic,FALSE);
4472     pic16_aopOp (right,ic,FALSE);
4473     pic16_aopOp (result,ic,TRUE);
4474
4475     /* special cases first */
4476     /* both are bits */
4477     if (AOP_TYPE(left) == AOP_CRY &&
4478         AOP_TYPE(right)== AOP_CRY) {
4479         genModbits(left,right,result);
4480         goto release ;
4481     }
4482
4483     /* if both are of size == 1 */
4484     if (AOP_SIZE(left) == 1 &&
4485         AOP_SIZE(right) == 1 ) {
4486         genModOneByte(left,right,result);
4487         goto release ;
4488     }
4489
4490     /* should have been converted to function call */
4491     assert(0);
4492
4493 release :
4494     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4495     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4496     pic16_freeAsmop(result,NULL,ic,TRUE); 
4497 }
4498
4499 /*-----------------------------------------------------------------*/
4500 /* genIfxJump :- will create a jump depending on the ifx           */
4501 /*-----------------------------------------------------------------*/
4502 /*
4503   note: May need to add parameter to indicate when a variable is in bit space.
4504 */
4505 static void genIfxJump (iCode *ic, char *jval)
4506 {
4507
4508     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4509     /* if true label then we jump if condition
4510     supplied is true */
4511     if ( IC_TRUE(ic) ) {
4512
4513         if(strcmp(jval,"a") == 0)
4514           emitSKPZ;
4515         else if (strcmp(jval,"c") == 0)
4516           emitSKPC;
4517         else {
4518           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4519           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4520         }
4521
4522         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4523         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4524
4525     }
4526     else {
4527         /* false label is present */
4528         if(strcmp(jval,"a") == 0)
4529           emitSKPNZ;
4530         else if (strcmp(jval,"c") == 0)
4531           emitSKPNC;
4532         else {
4533           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4534           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4535         }
4536
4537         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4538         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4539
4540     }
4541
4542
4543     /* mark the icode as generated */
4544     ic->generated = 1;
4545 }
4546
4547 #if 0
4548 // not needed ATM
4549
4550 /*-----------------------------------------------------------------*/
4551 /* genSkip                                                         */
4552 /*-----------------------------------------------------------------*/
4553 static void genSkip(iCode *ifx,int status_bit)
4554 {
4555   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4556   if(!ifx)
4557     return;
4558
4559   if ( IC_TRUE(ifx) ) {
4560     switch(status_bit) {
4561     case 'z':
4562       emitSKPNZ;
4563       break;
4564
4565     case 'c':
4566       emitSKPNC;
4567       break;
4568
4569     case 'd':
4570       emitSKPDC;
4571       break;
4572
4573     }
4574
4575     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4576     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4577
4578   } else {
4579
4580     switch(status_bit) {
4581
4582     case 'z':
4583       emitSKPZ;
4584       break;
4585
4586     case 'c':
4587       emitSKPC;
4588       break;
4589
4590     case 'd':
4591       emitSKPDC;
4592       break;
4593     }
4594     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4595     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4596
4597   }
4598
4599 }
4600 #endif
4601
4602 /*-----------------------------------------------------------------*/
4603 /* genSkipc                                                        */
4604 /*-----------------------------------------------------------------*/
4605 static void genSkipc(resolvedIfx *rifx)
4606 {
4607   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4608   
4609   if(!rifx)
4610     return;
4611
4612   if(rifx->condition)
4613     emitSKPC;
4614   else
4615     emitSKPNC;
4616
4617   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4618   rifx->generated = 1;
4619 }
4620
4621 /*-----------------------------------------------------------------*/
4622 /* genSkipz2                                                       */
4623 /*-----------------------------------------------------------------*/
4624 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4625 {
4626   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4627   
4628   if(!rifx)
4629     return;
4630
4631   if( (rifx->condition ^ invert_condition) & 1)
4632     emitSKPZ;
4633   else
4634     emitSKPNZ;
4635
4636   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4637   rifx->generated = 1;
4638 }
4639
4640 #if 0
4641 /*-----------------------------------------------------------------*/
4642 /* genSkipz                                                        */
4643 /*-----------------------------------------------------------------*/
4644 static void genSkipz(iCode *ifx, int condition)
4645 {
4646   if(!ifx)
4647     return;
4648
4649   if(condition)
4650     emitSKPNZ;
4651   else
4652     emitSKPZ;
4653
4654   if ( IC_TRUE(ifx) )
4655     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4656   else
4657     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4658
4659   if ( IC_TRUE(ifx) )
4660     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4661   else
4662     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4663
4664 }
4665 #endif
4666
4667 /*-----------------------------------------------------------------*/
4668 /* genSkipCond                                                     */
4669 /*-----------------------------------------------------------------*/
4670 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4671 {
4672   if(!rifx)
4673     return;
4674
4675   if(rifx->condition)
4676     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4677   else
4678     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4679
4680
4681   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4682   rifx->generated = 1;
4683 }
4684
4685 #if 0
4686 /*-----------------------------------------------------------------*/
4687 /* genChkZeroes :- greater or less than comparison                 */
4688 /*     For each byte in a literal that is zero, inclusive or the   */
4689 /*     the corresponding byte in the operand with W                */
4690 /*     returns true if any of the bytes are zero                   */
4691 /*-----------------------------------------------------------------*/
4692 static int genChkZeroes(operand *op, int lit,  int size)
4693 {
4694
4695   int i;
4696   int flag =1;
4697
4698   while(size--) {
4699     i = (lit >> (size*8)) & 0xff;
4700
4701     if(i==0) {
4702       if(flag) 
4703         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4704       else
4705         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4706       flag = 0;
4707     }
4708   }
4709
4710   return (flag==0);
4711 }
4712 #endif
4713
4714 /*-----------------------------------------------------------------*/
4715 /* genCmp :- greater or less than comparison                       */
4716 /*-----------------------------------------------------------------*/
4717 static void genCmp (operand *left,operand *right,
4718                     operand *result, iCode *ifx, int sign)
4719 {
4720   int size; //, offset = 0 ;
4721   unsigned long lit = 0L,i = 0;
4722   resolvedIfx rFalseIfx;
4723   //  resolvedIfx rTrueIfx;
4724   symbol *truelbl;
4725   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4726 /*
4727   if(ifx) {
4728     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4729     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4730   }
4731 */
4732
4733   resolveIfx(&rFalseIfx,ifx);
4734   truelbl  = newiTempLabel(NULL);
4735   size = max(AOP_SIZE(left),AOP_SIZE(right));
4736
4737   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4738
4739 #define _swapp
4740
4741   /* if literal is on the right then swap with left */
4742   if ((AOP_TYPE(right) == AOP_LIT)) {
4743     operand *tmp = right ;
4744     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4745     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4746 #ifdef _swapp
4747
4748     lit = (lit - 1) & mask;
4749     right = left;
4750     left = tmp;
4751     rFalseIfx.condition ^= 1;
4752 #endif
4753
4754   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4755     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4756   }
4757
4758
4759   //if(IC_TRUE(ifx) == NULL)
4760   /* if left & right are bit variables */
4761   if (AOP_TYPE(left) == AOP_CRY &&
4762       AOP_TYPE(right) == AOP_CRY ) {
4763     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4764     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4765   } else {
4766     /* subtract right from left if at the
4767        end the carry flag is set then we know that
4768        left is greater than right */
4769
4770     symbol *lbl  = newiTempLabel(NULL);
4771
4772 #if 0
4773         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4774                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
4775 #endif
4776
4777 #ifndef _swapp
4778     if(AOP_TYPE(right) == AOP_LIT) {
4779
4780       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4781
4782       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4783
4784       /* special cases */
4785
4786       if(lit == 0) {
4787
4788         if(sign != 0) 
4789           genSkipCond(&rFalseIfx,left,size-1,7);
4790         else 
4791           /* no need to compare to 0...*/
4792           /* NOTE: this is a de-generate compare that most certainly 
4793            *       creates some dead code. */
4794           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4795
4796         if(ifx) ifx->generated = 1;
4797         return;
4798
4799       }
4800       size--;
4801
4802       if(size == 0) {
4803         //i = (lit >> (size*8)) & 0xff;
4804         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4805         
4806         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4807
4808         i = ((0-lit) & 0xff);
4809         if(sign) {
4810           if( i == 0x81) { 
4811             /* lit is 0x7f, all signed chars are less than
4812              * this except for 0x7f itself */
4813             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4814             genSkipz2(&rFalseIfx,0);
4815           } else {
4816             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4817             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4818             genSkipc(&rFalseIfx);
4819           }
4820
4821         } else {
4822           if(lit == 1) {
4823             genSkipz2(&rFalseIfx,1);
4824           } else {
4825             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4826             genSkipc(&rFalseIfx);
4827           }
4828         }
4829
4830         if(ifx) ifx->generated = 1;
4831         return;
4832       }
4833
4834       /* chars are out of the way. now do ints and longs */
4835
4836
4837       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4838         
4839       /* special cases */
4840
4841       if(sign) {
4842
4843         if(lit == 0) {
4844           genSkipCond(&rFalseIfx,left,size,7);
4845           if(ifx) ifx->generated = 1;
4846           return;
4847         }
4848
4849         if(lit <0x100) {
4850           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4851
4852           //rFalseIfx.condition ^= 1;
4853           //genSkipCond(&rFalseIfx,left,size,7);
4854           //rFalseIfx.condition ^= 1;
4855
4856           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4857           if(rFalseIfx.condition)
4858             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4859           else
4860             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4861
4862           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4863           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4864           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4865
4866           while(size > 1)
4867             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4868
4869           if(rFalseIfx.condition) {
4870             emitSKPZ;
4871             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4872
4873           } else {
4874             emitSKPNZ;
4875           }
4876
4877           genSkipc(&rFalseIfx);
4878           pic16_emitpLabel(truelbl->key);
4879           if(ifx) ifx->generated = 1;
4880           return;
4881
4882         }
4883
4884         if(size == 1) {
4885
4886           if( (lit & 0xff) == 0) {
4887             /* lower byte is zero */
4888             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4889             i = ((lit >> 8) & 0xff) ^0x80;
4890             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4891             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4892             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4893             genSkipc(&rFalseIfx);
4894
4895
4896             if(ifx) ifx->generated = 1;
4897             return;
4898
4899           }
4900         } else {
4901           /* Special cases for signed longs */
4902           if( (lit & 0xffffff) == 0) {
4903             /* lower byte is zero */
4904             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4905             i = ((lit >> 8*3) & 0xff) ^0x80;
4906             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4907             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4908             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4909             genSkipc(&rFalseIfx);
4910
4911
4912             if(ifx) ifx->generated = 1;
4913             return;
4914
4915           }
4916
4917         }
4918
4919
4920         if(lit & (0x80 << (size*8))) {
4921           /* lit is negative */
4922           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4923
4924           //genSkipCond(&rFalseIfx,left,size,7);
4925
4926           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4927
4928           if(rFalseIfx.condition)
4929             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4930           else
4931             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4932
4933
4934         } else {
4935           /* lit is positive */
4936           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4937           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4938           if(rFalseIfx.condition)
4939             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4940           else
4941             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4942
4943         }
4944
4945         /*
4946           This works, but is only good for ints.
4947           It also requires a "known zero" register.
4948           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4949           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4950           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4951           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4952           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4953           genSkipc(&rFalseIfx);
4954
4955           pic16_emitpLabel(truelbl->key);
4956           if(ifx) ifx->generated = 1;
4957           return;
4958         **/
4959           
4960         /* There are no more special cases, so perform a general compare */
4961   
4962         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4963         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4964
4965         while(size--) {
4966
4967           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4968           emitSKPNZ;
4969           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4970         }
4971         //rFalseIfx.condition ^= 1;
4972         genSkipc(&rFalseIfx);
4973
4974         pic16_emitpLabel(truelbl->key);
4975
4976         if(ifx) ifx->generated = 1;
4977         return;
4978
4979
4980       }
4981
4982
4983       /* sign is out of the way. So now do an unsigned compare */
4984       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4985
4986
4987       /* General case - compare to an unsigned literal on the right.*/
4988
4989       i = (lit >> (size*8)) & 0xff;
4990       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4991       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4992       while(size--) {
4993         i = (lit >> (size*8)) & 0xff;
4994
4995         if(i) {
4996           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4997           emitSKPNZ;
4998           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4999         } else {
5000           /* this byte of the lit is zero, 
5001            *if it's not the last then OR in the variable */
5002           if(size)
5003             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5004         }
5005       }
5006
5007
5008       pic16_emitpLabel(lbl->key);
5009 //      pic16_emitpLabel(truelbl->key);
5010       //if(emitFinalCheck)
5011       genSkipc(&rFalseIfx);
5012       if(sign)
5013         pic16_emitpLabel(truelbl->key);
5014
5015       if(ifx) ifx->generated = 1;
5016       return;
5017
5018
5019     }
5020 #endif  // _swapp
5021
5022     if(AOP_TYPE(left) == AOP_LIT) {
5023       //symbol *lbl = newiTempLabel(NULL);
5024
5025       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5026
5027
5028       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5029
5030       /* Special cases */
5031       if((lit == 0) && (sign == 0)){
5032
5033         size--;
5034         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5035         while(size) 
5036           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5037
5038         genSkipz2(&rFalseIfx,0);
5039         if(ifx) ifx->generated = 1;
5040         return;
5041       }
5042
5043       if(size==1) {
5044         /* Special cases */
5045         lit &= 0xff;
5046         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5047           /* degenerate compare can never be true */
5048           if(rFalseIfx.condition == 0)
5049             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5050
5051           if(ifx) ifx->generated = 1;
5052           return;
5053         }
5054
5055         if(sign) {
5056           /* signed comparisons to a literal byte */
5057
5058           int lp1 = (lit+1) & 0xff;
5059
5060           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5061           switch (lp1) {
5062           case 0:
5063             rFalseIfx.condition ^= 1;
5064             genSkipCond(&rFalseIfx,right,0,7);
5065             break;
5066           case 0x7f:
5067             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5068             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5069             genSkipz2(&rFalseIfx,1);
5070             break;
5071           default:
5072             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5073             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5074             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5075             rFalseIfx.condition ^= 1;
5076             genSkipc(&rFalseIfx);
5077             break;
5078           }
5079         } else {
5080           /* unsigned comparisons to a literal byte */
5081
5082           switch(lit & 0xff ) {
5083           case 0:
5084             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5085             genSkipz2(&rFalseIfx,0);
5086             break;
5087           case 0x7f:
5088             rFalseIfx.condition ^= 1;
5089             genSkipCond(&rFalseIfx,right,0,7);
5090             break;
5091
5092           default:
5093             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5094             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5095             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5096             rFalseIfx.condition ^= 1;
5097             if (AOP_TYPE(result) == AOP_CRY)
5098               genSkipc(&rFalseIfx);
5099             else {
5100               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5101               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5102             }         
5103             break;
5104           }
5105         }
5106
5107         if(ifx) ifx->generated = 1;
5108         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5109                 goto check_carry;
5110         return;
5111
5112       } else {
5113
5114         /* Size is greater than 1 */
5115
5116         if(sign) {
5117           int lp1 = lit+1;
5118
5119           size--;
5120
5121           if(lp1 == 0) {
5122             /* this means lit = 0xffffffff, or -1 */
5123
5124
5125             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5126             rFalseIfx.condition ^= 1;
5127             genSkipCond(&rFalseIfx,right,size,7);
5128             if(ifx) ifx->generated = 1;
5129             return;
5130           }
5131
5132           if(lit == 0) {
5133             int s = size;
5134
5135             if(rFalseIfx.condition) {
5136               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5137               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5138             }
5139
5140             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5141             while(size--)
5142               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5143
5144
5145             emitSKPZ;
5146             if(rFalseIfx.condition) {
5147               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5148               pic16_emitpLabel(truelbl->key);
5149             }else {
5150               rFalseIfx.condition ^= 1;
5151               genSkipCond(&rFalseIfx,right,s,7);
5152             }
5153
5154             if(ifx) ifx->generated = 1;
5155             return;
5156           }
5157
5158           if((size == 1) &&  (0 == (lp1&0xff))) {
5159             /* lower byte of signed word is zero */
5160             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5161             i = ((lp1 >> 8) & 0xff) ^0x80;
5162             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5163             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5164             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5165             rFalseIfx.condition ^= 1;
5166             genSkipc(&rFalseIfx);
5167
5168
5169             if(ifx) ifx->generated = 1;
5170             return;
5171           }
5172
5173           if(lit & (0x80 << (size*8))) {
5174             /* Lit is less than zero */
5175             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5176             //rFalseIfx.condition ^= 1;
5177             //genSkipCond(&rFalseIfx,left,size,7);
5178             //rFalseIfx.condition ^= 1;
5179             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5180             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5181
5182             if(rFalseIfx.condition)
5183               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5184             else
5185               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5186
5187
5188           } else {
5189             /* Lit is greater than or equal to zero */
5190             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5191             //rFalseIfx.condition ^= 1;
5192             //genSkipCond(&rFalseIfx,right,size,7);
5193             //rFalseIfx.condition ^= 1;
5194
5195             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5196             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5197
5198             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5199             if(rFalseIfx.condition)
5200               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5201             else
5202               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5203
5204           }
5205
5206
5207           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5208           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5209
5210           while(size--) {
5211
5212             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5213             emitSKPNZ;
5214             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5215           }
5216           rFalseIfx.condition ^= 1;
5217           //rFalseIfx.condition = 1;
5218           genSkipc(&rFalseIfx);
5219
5220           pic16_emitpLabel(truelbl->key);
5221
5222           if(ifx) ifx->generated = 1;
5223           return;
5224           // end of if (sign)
5225         } else {
5226
5227           /* compare word or long to an unsigned literal on the right.*/
5228
5229
5230           size--;
5231           if(lit < 0xff) {
5232             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5233             switch (lit) {
5234             case 0:
5235               break; /* handled above */
5236 /*
5237             case 0xff:
5238               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5239               while(size--)
5240                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5241               genSkipz2(&rFalseIfx,0);
5242               break;
5243 */
5244             default:
5245               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5246               while(--size)
5247                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5248
5249               emitSKPZ;
5250               if(rFalseIfx.condition)
5251                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5252               else
5253                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5254
5255
5256               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5257               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5258
5259               rFalseIfx.condition ^= 1;
5260               genSkipc(&rFalseIfx);
5261             }
5262
5263             pic16_emitpLabel(truelbl->key);
5264
5265             if(ifx) ifx->generated = 1;
5266             return;
5267           }
5268
5269
5270           lit++;
5271           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5272           i = (lit >> (size*8)) & 0xff;
5273
5274           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5275           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5276
5277           while(size--) {
5278             i = (lit >> (size*8)) & 0xff;
5279
5280             if(i) {
5281               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5282               emitSKPNZ;
5283               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5284             } else {
5285               /* this byte of the lit is zero, 
5286                * if it's not the last then OR in the variable */
5287               if(size)
5288                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5289             }
5290           }
5291
5292
5293           pic16_emitpLabel(lbl->key);
5294
5295           rFalseIfx.condition ^= 1;
5296
5297           genSkipc(&rFalseIfx);
5298         }
5299
5300         if(sign)
5301           pic16_emitpLabel(truelbl->key);
5302         if(ifx) ifx->generated = 1;
5303         return;
5304       }
5305     }
5306     /* Compare two variables */
5307
5308     DEBUGpic16_emitcode(";sign","%d",sign);
5309
5310     size--;
5311     if(sign) {
5312       /* Sigh. thus sucks... */
5313       if(size) {
5314         pCodeOp *pctemp;
5315         
5316         pctemp = pic16_popGetTempReg();
5317         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5318         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5319         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5320         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5321         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5322         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5323         pic16_popReleaseTempReg(pctemp);
5324       } else {
5325         /* Signed char comparison */
5326         /* Special thanks to Nikolai Golovchenko for this snippet */
5327         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5328         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5329         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5330         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5331         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5332         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5333
5334         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5335         genSkipc(&rFalseIfx);
5336           
5337         if(ifx) ifx->generated = 1;
5338         return;
5339       }
5340
5341     } else {
5342
5343       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5344       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5345     }
5346
5347
5348     /* The rest of the bytes of a multi-byte compare */
5349     while (size) {
5350
5351       emitSKPZ;
5352       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5353       size--;
5354
5355       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5356       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5357
5358
5359     }
5360
5361     pic16_emitpLabel(lbl->key);
5362
5363     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5364     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5365         (AOP_TYPE(result) == AOP_REG)) {
5366       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5367       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5368     } else {
5369       genSkipc(&rFalseIfx);
5370     }         
5371     //genSkipc(&rFalseIfx);
5372     if(ifx) ifx->generated = 1;
5373
5374     return;
5375
5376   }
5377
5378 check_carry:
5379   if ((AOP_TYPE(result) != AOP_CRY) 
5380         && AOP_SIZE(result)) {
5381     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5382
5383     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5384
5385     pic16_outBitC(result);
5386   } else {
5387     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5388     /* if the result is used in the next
5389        ifx conditional branch then generate
5390        code a little differently */
5391     if (ifx )
5392       genIfxJump (ifx,"c");
5393     else
5394       pic16_outBitC(result);
5395     /* leave the result in acc */
5396   }
5397
5398 }
5399
5400 /*-----------------------------------------------------------------*/
5401 /* genCmpGt :- greater than comparison                             */
5402 /*-----------------------------------------------------------------*/
5403 static void genCmpGt (iCode *ic, iCode *ifx)
5404 {
5405     operand *left, *right, *result;
5406     sym_link *letype , *retype;
5407     int sign ;
5408
5409     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5410     left = IC_LEFT(ic);
5411     right= IC_RIGHT(ic);
5412     result = IC_RESULT(ic);
5413
5414     letype = getSpec(operandType(left));
5415     retype =getSpec(operandType(right));
5416     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5417     /* assign the amsops */
5418     pic16_aopOp (left,ic,FALSE);
5419     pic16_aopOp (right,ic,FALSE);
5420     pic16_aopOp (result,ic,TRUE);
5421
5422     genCmp(right, left, result, ifx, sign);
5423
5424     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5425     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5426     pic16_freeAsmop(result,NULL,ic,TRUE); 
5427 }
5428
5429 /*-----------------------------------------------------------------*/
5430 /* genCmpLt - less than comparisons                                */
5431 /*-----------------------------------------------------------------*/
5432 static void genCmpLt (iCode *ic, iCode *ifx)
5433 {
5434     operand *left, *right, *result;
5435     sym_link *letype , *retype;
5436     int sign ;
5437
5438     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5439     left = IC_LEFT(ic);
5440     right= IC_RIGHT(ic);
5441     result = IC_RESULT(ic);
5442
5443     letype = getSpec(operandType(left));
5444     retype =getSpec(operandType(right));
5445     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5446
5447     /* assign the amsops */
5448     pic16_aopOp (left,ic,FALSE);
5449     pic16_aopOp (right,ic,FALSE);
5450     pic16_aopOp (result,ic,TRUE);
5451
5452     genCmp(left, right, result, ifx, sign);
5453
5454     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5455     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5456     pic16_freeAsmop(result,NULL,ic,TRUE); 
5457 }
5458
5459 #if 0
5460 // not needed ATM
5461 // FIXME reenable literal optimisation when the pic16 port is stable
5462
5463 /*-----------------------------------------------------------------*/
5464 /* genc16bit2lit - compare a 16 bit value to a literal             */
5465 /*-----------------------------------------------------------------*/
5466 static void genc16bit2lit(operand *op, int lit, int offset)
5467 {
5468   int i;
5469
5470   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
5471   if( (lit&0xff) == 0) 
5472     i=1;
5473   else
5474     i=0;
5475
5476   switch( BYTEofLONG(lit,i)) { 
5477   case 0:
5478     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5479     break;
5480   case 1:
5481     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5482     break;
5483   case 0xff:
5484     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5485     break;
5486   default:
5487     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5488     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5489   }
5490
5491   i ^= 1;
5492
5493   switch( BYTEofLONG(lit,i)) { 
5494   case 0:
5495     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5496     break;
5497   case 1:
5498     emitSKPNZ;
5499     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5500     break;
5501   case 0xff:
5502     emitSKPNZ;
5503     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5504     break;
5505   default:
5506     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5507     emitSKPNZ;
5508     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5509
5510   }
5511
5512 }
5513 #endif
5514
5515 #if 0
5516 // not needed ATM
5517 /*-----------------------------------------------------------------*/
5518 /* gencjneshort - compare and jump if not equal                    */
5519 /*-----------------------------------------------------------------*/
5520 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5521 {
5522   int size = max(AOP_SIZE(left),AOP_SIZE(right));
5523   int offset = 0;
5524   int res_offset = 0;  /* the result may be a different size then left or right */
5525   int res_size = AOP_SIZE(result);
5526   resolvedIfx rIfx;
5527   symbol *lbl, *lbl_done;
5528
5529   unsigned long lit = 0L;
5530   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5531
5532   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5533   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5534   if(result)
5535     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
5536   resolveIfx(&rIfx,ifx);
5537   lbl =  newiTempLabel(NULL);
5538   lbl_done =  newiTempLabel(NULL);
5539
5540
5541   /* if the left side is a literal or 
5542      if the right is in a pointer register and left 
5543      is not */
5544   if ((AOP_TYPE(left) == AOP_LIT) || 
5545       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5546     operand *t = right;
5547     right = left;
5548     left = t;
5549   }
5550   if(AOP_TYPE(right) == AOP_LIT)
5551     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5552
5553   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5554     preserve_result = 1;
5555
5556   if(result && !preserve_result)
5557     {
5558       int i;
5559       for(i = 0; i < AOP_SIZE(result); i++)
5560         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5561     }
5562
5563
5564   /* if the right side is a literal then anything goes */
5565   if (AOP_TYPE(right) == AOP_LIT &&
5566       AOP_TYPE(left) != AOP_DIR ) {
5567     switch(size) {
5568     case 2:
5569       genc16bit2lit(left, lit, 0);
5570       emitSKPZ;
5571       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5572       break;
5573     default:
5574       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5575       while (size--) {
5576         if(lit & 0xff) {
5577           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5578           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5579         } else {
5580           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5581         }
5582
5583         emitSKPZ;
5584         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5585         offset++;
5586         if(res_offset < res_size-1)
5587           res_offset++;
5588         lit >>= 8;
5589       }
5590       break;
5591     }
5592   }
5593
5594   /* if the right side is in a register or in direct space or
5595      if the left is a pointer register & right is not */    
5596   else if (AOP_TYPE(right) == AOP_REG ||
5597            AOP_TYPE(right) == AOP_DIR || 
5598            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5599            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5600     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5601     int lbl_key = lbl->key;
5602
5603     if(result) {
5604       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5605       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5606     }else {
5607       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5608       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5609               __FUNCTION__,__LINE__);
5610       return;
5611     }
5612    
5613 /*     switch(size) { */
5614 /*     case 2: */
5615 /*       genc16bit2lit(left, lit, 0); */
5616 /*       emitSKPNZ; */
5617 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5618 /*       break; */
5619 /*     default: */
5620     while (size--) {
5621       int emit_skip=1;
5622       if((AOP_TYPE(left) == AOP_DIR) && 
5623          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5624
5625         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5626         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5627
5628       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5629             
5630         switch (lit & 0xff) {
5631         case 0:
5632           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5633           break;
5634         case 1:
5635           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5636           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5637           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5638           emit_skip=0;
5639           break;
5640         case 0xff:
5641           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5642           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5643           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5644           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5645           emit_skip=0;
5646           break;
5647         default:
5648           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5649           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5650         }
5651         lit >>= 8;
5652
5653       } else {
5654         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5655       }
5656       if(emit_skip) {
5657         if(AOP_TYPE(result) == AOP_CRY) {
5658           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5659           if(rIfx.condition)
5660             emitSKPNZ;
5661           else
5662             emitSKPZ;
5663           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5664         } else {
5665           /* fix me. probably need to check result size too */
5666           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5667           if(rIfx.condition)
5668             emitSKPZ;
5669           else
5670             emitSKPNZ;
5671           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5672           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5673         }
5674         if(ifx)
5675           ifx->generated=1;
5676       }
5677       emit_skip++;
5678       offset++;
5679       if(res_offset < res_size-1)
5680         res_offset++;
5681     }
5682 /*       break; */
5683 /*     } */
5684   } else if(AOP_TYPE(right) == AOP_REG &&
5685             AOP_TYPE(left) != AOP_DIR){
5686
5687     while(size--) {
5688       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5689       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5690       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5691       if(rIfx.condition)
5692         emitSKPNZ;
5693       else
5694         emitSKPZ;
5695       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5696       offset++;
5697       if(res_offset < res_size-1)
5698         res_offset++;
5699     }
5700       
5701   }else{
5702     /* right is a pointer reg need both a & b */
5703     while(size--) {
5704       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5705       if(strcmp(l,"b"))
5706         pic16_emitcode("mov","b,%s",l);
5707       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5708       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5709       offset++;
5710     }
5711   }
5712
5713   if(result && preserve_result)
5714     {
5715       int i;
5716       for(i = 0; i < AOP_SIZE(result); i++)
5717         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5718     }
5719
5720   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5721
5722   if(result && preserve_result)
5723     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5724
5725   if(!rIfx.condition)
5726     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5727
5728   pic16_emitpLabel(lbl->key);
5729
5730   if(result && preserve_result)
5731     {
5732       int i;
5733       for(i = 0; i < AOP_SIZE(result); i++)
5734         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5735
5736       pic16_emitpLabel(lbl_done->key);
5737    }
5738
5739   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5740
5741   if(ifx)
5742     ifx->generated = 1;
5743 }
5744 #endif
5745
5746 #if 0
5747 /*-----------------------------------------------------------------*/
5748 /* gencjne - compare and jump if not equal                         */
5749 /*-----------------------------------------------------------------*/
5750 static void gencjne(operand *left, operand *right, iCode *ifx)
5751 {
5752     symbol *tlbl  = newiTempLabel(NULL);
5753
5754     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5755     gencjneshort(left, right, lbl);
5756
5757     pic16_emitcode("mov","a,%s",one);
5758     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5759     pic16_emitcode("","%05d_DS_:",lbl->key+100);
5760     pic16_emitcode("clr","a");
5761     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5762
5763     pic16_emitpLabel(lbl->key);
5764     pic16_emitpLabel(tlbl->key);
5765
5766 }
5767 #endif
5768
5769
5770 /*-----------------------------------------------------------------*/
5771 /* is_LitOp - check if operand has to be treated as literal        */
5772 /*-----------------------------------------------------------------*/
5773 static bool is_LitOp(operand *op)
5774 {
5775   return (AOP_TYPE(op) == AOP_LIT)
5776       || ( (AOP_TYPE(op) == AOP_PCODE)
5777           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5778               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));  
5779 }
5780
5781 /*-----------------------------------------------------------------*/
5782 /* is_LitAOp - check if operand has to be treated as literal        */
5783 /*-----------------------------------------------------------------*/
5784 static bool is_LitAOp(asmop *aop)
5785 {
5786   return (aop->type == AOP_LIT)
5787       || ( (aop->type == AOP_PCODE)
5788           && ( (aop->aopu.pcop->type == PO_LITERAL)
5789               || (aop->aopu.pcop->type == PO_IMMEDIATE) ));  
5790 }
5791
5792
5793
5794 /*-----------------------------------------------------------------*/
5795 /* genCmpEq - generates code for equal to                          */
5796 /*-----------------------------------------------------------------*/
5797 static void genCmpEq (iCode *ic, iCode *ifx)
5798 {
5799   operand *left, *right, *result;
5800   symbol *falselbl = newiTempLabel(NULL);
5801   symbol *donelbl = newiTempLabel(NULL);
5802
5803   int preserve_result = 0;
5804   int generate_result = 0;
5805   int i=0;
5806
5807   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5808   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5809   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5810  
5811   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5812   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5813
5814   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5815     {
5816       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5817       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5818       goto release;
5819     }
5820
5821   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5822     {
5823       operand *tmp = right ;
5824       right = left;
5825       left = tmp;
5826     }
5827
5828   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5829     preserve_result = 1;
5830
5831   if(result && AOP_SIZE(result))
5832     generate_result = 1;
5833
5834   if(generate_result && !preserve_result)
5835     {
5836       for(i = 0; i < AOP_SIZE(result); i++)
5837         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5838     }
5839
5840   for(i=0; i < AOP_SIZE(left); i++)
5841     {
5842       if(AOP_TYPE(left) != AOP_ACC)
5843         {
5844           if(is_LitOp(left))
5845             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5846           else
5847             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5848         }
5849       if(is_LitOp(right))
5850         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
5851       else
5852         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
5853
5854       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5855     }
5856
5857   // result == true
5858
5859   if(generate_result && preserve_result)
5860     {
5861       for(i = 0; i < AOP_SIZE(result); i++)
5862         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5863     }
5864
5865   if(generate_result)
5866     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5867
5868   if(generate_result && preserve_result)
5869     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5870
5871   if(ifx && IC_TRUE(ifx))
5872     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5873
5874   if(ifx && IC_FALSE(ifx))
5875     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5876
5877   pic16_emitpLabel(falselbl->key);
5878
5879   // result == false
5880
5881   if(ifx && IC_FALSE(ifx))
5882     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5883
5884   if(generate_result && preserve_result)
5885     {
5886       for(i = 0; i < AOP_SIZE(result); i++)
5887         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5888     }
5889
5890   pic16_emitpLabel(donelbl->key);
5891
5892   if(ifx)
5893     ifx->generated = 1;
5894
5895 release:
5896   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5897   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5898   pic16_freeAsmop(result,NULL,ic,TRUE);
5899
5900 }
5901
5902
5903 #if 0
5904 // old version kept for reference
5905
5906 /*-----------------------------------------------------------------*/
5907 /* genCmpEq - generates code for equal to                          */
5908 /*-----------------------------------------------------------------*/
5909 static void genCmpEq (iCode *ic, iCode *ifx)
5910 {
5911     operand *left, *right, *result;
5912     unsigned long lit = 0L;
5913     int size,offset=0;
5914     symbol *falselbl  = newiTempLabel(NULL);
5915
5916
5917     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5918
5919     if(ifx)
5920       DEBUGpic16_emitcode ("; ifx is non-null","");
5921     else
5922       DEBUGpic16_emitcode ("; ifx is null","");
5923
5924     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5925     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5926     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5927
5928     size = max(AOP_SIZE(left),AOP_SIZE(right));
5929
5930     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5931
5932     /* if literal, literal on the right or 
5933     if the right is in a pointer register and left 
5934     is not */
5935     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
5936         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5937       operand *tmp = right ;
5938       right = left;
5939       left = tmp;
5940     }
5941
5942
5943     if(ifx && !AOP_SIZE(result)){
5944         symbol *tlbl;
5945         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
5946         /* if they are both bit variables */
5947         if (AOP_TYPE(left) == AOP_CRY &&
5948             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5949                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
5950             if(AOP_TYPE(right) == AOP_LIT){
5951                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5952                 if(lit == 0L){
5953                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5954                     pic16_emitcode("cpl","c");
5955                 } else if(lit == 1L) {
5956                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5957                 } else {
5958                     pic16_emitcode("clr","c");
5959                 }
5960                 /* AOP_TYPE(right) == AOP_CRY */
5961             } else {
5962                 symbol *lbl = newiTempLabel(NULL);
5963                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5964                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5965                 pic16_emitcode("cpl","c");
5966                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5967             }
5968             /* if true label then we jump if condition
5969             supplied is true */
5970             tlbl = newiTempLabel(NULL);
5971             if ( IC_TRUE(ifx) ) {
5972                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5973                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5974             } else {
5975                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5976                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5977             }
5978             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5979
5980                 {
5981                 /* left and right are both bit variables, result is carry */
5982                         resolvedIfx rIfx;
5983               
5984                         resolveIfx(&rIfx,ifx);
5985
5986                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5987                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5988                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5989                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5990                         genSkipz2(&rIfx,0);
5991                 }
5992         } else {
5993
5994                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
5995
5996                         /* They're not both bit variables. Is the right a literal? */
5997                         if(AOP_TYPE(right) == AOP_LIT) {
5998                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5999             
6000                         switch(size) {
6001
6002                                 case 1:
6003                                         switch(lit & 0xff) {
6004                                                 case 1:
6005                                                                 if ( IC_TRUE(ifx) ) {
6006                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6007                                                                         emitSKPNZ;
6008                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6009                                                                 } else {
6010                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6011                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6012                                                                 }
6013                                                                 break;
6014                                                 case 0xff:
6015                                                                 if ( IC_TRUE(ifx) ) {
6016                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6017                                                                         emitSKPNZ;
6018                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6019                                                                 } else {
6020                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6021                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6022                                                                 }
6023                                                                 break;
6024                                                 default:
6025                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6026                                                                 if(lit)
6027                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6028                                                                 genSkip(ifx,'z');
6029                                         } // switch lit
6030
6031
6032                                         /* end of size == 1 */
6033                                         break;
6034               
6035                                 case 2:
6036                                         genc16bit2lit(left,lit,offset);
6037                                         genSkip(ifx,'z');
6038                                         break;
6039                                         /* end of size == 2 */
6040
6041                                 default:
6042                                         /* size is 4 */
6043                                         if(lit==0) {
6044                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6045                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6046                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6047                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6048                                                 genSkip(ifx,'z');
6049                                         } else {
6050                                                 /* search for patterns that can be optimized */
6051
6052                                                 genc16bit2lit(left,lit,0);
6053                                                 lit >>= 16;
6054                                                 if(lit) {
6055                                                                 if(IC_TRUE(ifx))
6056                                                                 emitSKPZ; // if hi word unequal
6057                                                                 else
6058                                                                 emitSKPNZ; // if hi word equal
6059                                                                 // fail early
6060                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6061                                                         genc16bit2lit(left,lit,2);
6062                                                         genSkip(ifx,'z');
6063                                                 } else {
6064                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6065                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6066                                                         genSkip(ifx,'z');
6067                                                 }
6068                                         }
6069                                                 pic16_emitpLabel(falselbl->key);
6070                                                 break;
6071
6072                         } // switch size
6073           
6074                         ifx->generated = 1;
6075                         goto release ;
6076             
6077
6078           } else if(AOP_TYPE(right) == AOP_CRY ) {
6079             /* we know the left is not a bit, but that the right is */
6080             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6081             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6082                       pic16_popGet(AOP(right),offset));
6083             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6084
6085             /* if the two are equal, then W will be 0 and the Z bit is set
6086              * we could test Z now, or go ahead and check the high order bytes if
6087              * the variable we're comparing is larger than a byte. */
6088
6089             while(--size)
6090               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6091
6092             if ( IC_TRUE(ifx) ) {
6093               emitSKPNZ;
6094               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6095               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6096             } else {
6097               emitSKPZ;
6098               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6099               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6100             }
6101
6102           } else {
6103             /* They're both variables that are larger than bits */
6104             int s = size;
6105
6106             tlbl = newiTempLabel(NULL);
6107
6108             while(size--) {
6109               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6110               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6111
6112               if ( IC_TRUE(ifx) ) {
6113                 if(size) {
6114                   emitSKPZ;
6115                 
6116                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6117
6118                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6119                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6120                 } else {
6121                   emitSKPNZ;
6122
6123                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6124
6125
6126                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6127                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6128                 }
6129               } else {
6130                 emitSKPZ;
6131
6132                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6133
6134                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6135                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6136               }
6137               offset++;
6138             }
6139             if(s>1 && IC_TRUE(ifx)) {
6140               pic16_emitpLabel(tlbl->key);
6141               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
6142             }
6143           }
6144         }
6145         /* mark the icode as generated */
6146         ifx->generated = 1;
6147         goto release ;
6148     }
6149
6150     /* if they are both bit variables */
6151     if (AOP_TYPE(left) == AOP_CRY &&
6152         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6153         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
6154         if(AOP_TYPE(right) == AOP_LIT){
6155             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6156             if(lit == 0L){
6157                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6158                 pic16_emitcode("cpl","c");
6159             } else if(lit == 1L) {
6160                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6161             } else {
6162                 pic16_emitcode("clr","c");
6163             }
6164             /* AOP_TYPE(right) == AOP_CRY */
6165         } else {
6166             symbol *lbl = newiTempLabel(NULL);
6167             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6168             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6169             pic16_emitcode("cpl","c");
6170             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6171         }
6172         /* c = 1 if egal */
6173         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6174             pic16_outBitC(result);
6175             goto release ;
6176         }
6177         if (ifx) {
6178             genIfxJump (ifx,"c");
6179             goto release ;
6180         }
6181         /* if the result is used in an arithmetic operation
6182         then put the result in place */
6183         pic16_outBitC(result);
6184     } else {
6185       
6186       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
6187       gencjne(left,right,result,ifx);
6188 /*
6189       if(ifx) 
6190         gencjne(left,right,newiTempLabel(NULL));
6191       else {
6192         if(IC_TRUE(ifx)->key)
6193           gencjne(left,right,IC_TRUE(ifx)->key);
6194         else
6195           gencjne(left,right,IC_FALSE(ifx)->key);
6196         ifx->generated = 1;
6197         goto release ;
6198       }
6199       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6200         pic16_aopPut(AOP(result),"a",0);
6201         goto release ;
6202       }
6203
6204       if (ifx) {
6205         genIfxJump (ifx,"a");
6206         goto release ;
6207       }
6208 */
6209       /* if the result is used in an arithmetic operation
6210          then put the result in place */
6211 /*
6212       if (AOP_TYPE(result) != AOP_CRY) 
6213         pic16_outAcc(result);
6214 */
6215       /* leave the result in acc */
6216     }
6217
6218 release:
6219     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6220     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6221     pic16_freeAsmop(result,NULL,ic,TRUE);
6222 }
6223 #endif
6224
6225 /*-----------------------------------------------------------------*/
6226 /* ifxForOp - returns the icode containing the ifx for operand     */
6227 /*-----------------------------------------------------------------*/
6228 static iCode *ifxForOp ( operand *op, iCode *ic )
6229 {
6230     /* if true symbol then needs to be assigned */
6231     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6232     if (IS_TRUE_SYMOP(op))
6233         return NULL ;
6234
6235     /* if this has register type condition and
6236     the next instruction is ifx with the same operand
6237     and live to of the operand is upto the ifx only then */
6238     if (ic->next
6239         && ic->next->op == IFX
6240         && IC_COND(ic->next)->key == op->key
6241         && OP_SYMBOL(op)->liveTo <= ic->next->seq
6242         ) {
6243                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6244           return ic->next;
6245     }
6246
6247     if (ic->next &&
6248         ic->next->op == IFX &&
6249         IC_COND(ic->next)->key == op->key) {
6250       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6251       return ic->next;
6252     }
6253
6254     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6255     if (ic->next &&
6256         ic->next->op == IFX)
6257       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6258
6259     if (ic->next &&
6260         ic->next->op == IFX &&
6261         IC_COND(ic->next)->key == op->key) {
6262       DEBUGpic16_emitcode ("; "," key is okay");
6263       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6264                            OP_SYMBOL(op)->liveTo,
6265                            ic->next->seq);
6266     }
6267
6268 #if 0
6269     /* the code below is completely untested
6270      * it just allows ulong2fs.c compile -- VR */
6271          
6272     ic = ic->next;
6273     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6274                                         __FILE__, __FUNCTION__, __LINE__);
6275         
6276     /* if this has register type condition and
6277     the next instruction is ifx with the same operand
6278     and live to of the operand is upto the ifx only then */
6279     if (ic->next &&
6280         ic->next->op == IFX &&
6281         IC_COND(ic->next)->key == op->key &&
6282         OP_SYMBOL(op)->liveTo <= ic->next->seq )
6283         return ic->next;
6284
6285     if (ic->next &&
6286         ic->next->op == IFX &&
6287         IC_COND(ic->next)->key == op->key) {
6288       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6289       return ic->next;
6290     }
6291
6292     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6293                                         __FILE__, __FUNCTION__, __LINE__);
6294
6295 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
6296 #endif
6297
6298     return NULL;
6299 }
6300 /*-----------------------------------------------------------------*/
6301 /* genAndOp - for && operation                                     */
6302 /*-----------------------------------------------------------------*/
6303 static void genAndOp (iCode *ic)
6304 {
6305     operand *left,*right, *result;
6306 /*     symbol *tlbl; */
6307
6308     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6309     /* note here that && operations that are in an
6310     if statement are taken away by backPatchLabels
6311     only those used in arthmetic operations remain */
6312     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6313     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6314     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6315
6316     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6317
6318     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6319     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6320     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6321
6322     /* if both are bit variables */
6323 /*     if (AOP_TYPE(left) == AOP_CRY && */
6324 /*         AOP_TYPE(right) == AOP_CRY ) { */
6325 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6326 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6327 /*         pic16_outBitC(result); */
6328 /*     } else { */
6329 /*         tlbl = newiTempLabel(NULL); */
6330 /*         pic16_toBoolean(left);     */
6331 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6332 /*         pic16_toBoolean(right); */
6333 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6334 /*         pic16_outBitAcc(result); */
6335 /*     } */
6336
6337     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6338     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6339     pic16_freeAsmop(result,NULL,ic,TRUE);
6340 }
6341
6342
6343 /*-----------------------------------------------------------------*/
6344 /* genOrOp - for || operation                                      */
6345 /*-----------------------------------------------------------------*/
6346 /*
6347   tsd pic port -
6348   modified this code, but it doesn't appear to ever get called
6349 */
6350
6351 static void genOrOp (iCode *ic)
6352 {
6353     operand *left,*right, *result;
6354     symbol *tlbl;
6355
6356     /* note here that || operations that are in an
6357     if statement are taken away by backPatchLabels
6358     only those used in arthmetic operations remain */
6359     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6360     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6361     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6362     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6363
6364     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6365
6366     /* if both are bit variables */
6367     if (AOP_TYPE(left) == AOP_CRY &&
6368         AOP_TYPE(right) == AOP_CRY ) {
6369       pic16_emitcode("clrc","");
6370       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6371                AOP(left)->aopu.aop_dir,
6372                AOP(left)->aopu.aop_dir);
6373       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6374                AOP(right)->aopu.aop_dir,
6375                AOP(right)->aopu.aop_dir);
6376       pic16_emitcode("setc","");
6377
6378     } else {
6379         tlbl = newiTempLabel(NULL);
6380         pic16_toBoolean(left);
6381         emitSKPZ;
6382         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
6383         pic16_toBoolean(right);
6384         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6385
6386         pic16_outBitAcc(result);
6387     }
6388
6389     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6390     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6391     pic16_freeAsmop(result,NULL,ic,TRUE);            
6392 }
6393
6394 /*-----------------------------------------------------------------*/
6395 /* isLiteralBit - test if lit == 2^n                               */
6396 /*-----------------------------------------------------------------*/
6397 static int isLiteralBit(unsigned long lit)
6398 {
6399     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6400     0x100L,0x200L,0x400L,0x800L,
6401     0x1000L,0x2000L,0x4000L,0x8000L,
6402     0x10000L,0x20000L,0x40000L,0x80000L,
6403     0x100000L,0x200000L,0x400000L,0x800000L,
6404     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6405     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6406     int idx;
6407     
6408     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6409     for(idx = 0; idx < 32; idx++)
6410         if(lit == pw[idx])
6411             return idx+1;
6412     return 0;
6413 }
6414
6415 /*-----------------------------------------------------------------*/
6416 /* continueIfTrue -                                                */
6417 /*-----------------------------------------------------------------*/
6418 static void continueIfTrue (iCode *ic)
6419 {
6420     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6421     if(IC_TRUE(ic))
6422         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6423     ic->generated = 1;
6424 }
6425
6426 /*-----------------------------------------------------------------*/
6427 /* jmpIfTrue -                                                     */
6428 /*-----------------------------------------------------------------*/
6429 static void jumpIfTrue (iCode *ic)
6430 {
6431     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6432     if(!IC_TRUE(ic))
6433         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6434     ic->generated = 1;
6435 }
6436
6437 /*-----------------------------------------------------------------*/
6438 /* jmpTrueOrFalse -                                                */
6439 /*-----------------------------------------------------------------*/
6440 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6441 {
6442     // ugly but optimized by peephole
6443     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6444     if(IC_TRUE(ic)){
6445         symbol *nlbl = newiTempLabel(NULL);
6446         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
6447         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6448         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6449         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6450     }
6451     else{
6452         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6453         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6454     }
6455     ic->generated = 1;
6456 }
6457
6458 /*-----------------------------------------------------------------*/
6459 /* genAnd  - code for and                                          */
6460 /*-----------------------------------------------------------------*/
6461 static void genAnd (iCode *ic, iCode *ifx)
6462 {
6463   operand *left, *right, *result;
6464   int size, offset=0;  
6465   unsigned long lit = 0L;
6466   int bytelit = 0;
6467   resolvedIfx rIfx;
6468
6469
6470   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6471   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6472   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6473   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6474
6475   resolveIfx(&rIfx,ifx);
6476
6477   /* if left is a literal & right is not then exchange them */
6478   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6479       AOP_NEEDSACC(left)) {
6480     operand *tmp = right ;
6481     right = left;
6482     left = tmp;
6483   }
6484
6485   /* if result = right then exchange them */
6486   if(pic16_sameRegs(AOP(result),AOP(right))){
6487     operand *tmp = right ;
6488     right = left;
6489     left = tmp;
6490   }
6491
6492   /* if right is bit then exchange them */
6493   if (AOP_TYPE(right) == AOP_CRY &&
6494       AOP_TYPE(left) != AOP_CRY){
6495     operand *tmp = right ;
6496     right = left;
6497     left = tmp;
6498   }
6499   if(AOP_TYPE(right) == AOP_LIT)
6500     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6501
6502   size = AOP_SIZE(result);
6503
6504   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6505
6506   // if(bit & yy)
6507   // result = bit & yy;
6508   if (AOP_TYPE(left) == AOP_CRY){
6509     // c = bit & literal;
6510     if(AOP_TYPE(right) == AOP_LIT){
6511       if(lit & 1) {
6512         if(size && pic16_sameRegs(AOP(result),AOP(left)))
6513           // no change
6514           goto release;
6515         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6516       } else {
6517         // bit(result) = 0;
6518         if(size && (AOP_TYPE(result) == AOP_CRY)){
6519           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6520           goto release;
6521         }
6522         if((AOP_TYPE(result) == AOP_CRY) && ifx){
6523           jumpIfTrue(ifx);
6524           goto release;
6525         }
6526         pic16_emitcode("clr","c");
6527       }
6528     } else {
6529       if (AOP_TYPE(right) == AOP_CRY){
6530         // c = bit & bit;
6531         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6532         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6533       } else {
6534         // c = bit & val;
6535         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6536         // c = lsb
6537         pic16_emitcode("rrc","a");
6538         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6539       }
6540     }
6541     // bit = c
6542     // val = c
6543     if(size)
6544       pic16_outBitC(result);
6545     // if(bit & ...)
6546     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6547       genIfxJump(ifx, "c");           
6548     goto release ;
6549   }
6550
6551   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6552   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6553   if((AOP_TYPE(right) == AOP_LIT) &&
6554      (AOP_TYPE(result) == AOP_CRY) &&
6555      (AOP_TYPE(left) != AOP_CRY)){
6556     int posbit = isLiteralBit(lit);
6557     /* left &  2^n */
6558     if(posbit){
6559       posbit--;
6560       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6561       // bit = left & 2^n
6562       if(size)
6563         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6564       // if(left &  2^n)
6565       else{
6566         if(ifx){
6567 /*
6568           if(IC_TRUE(ifx)) {
6569             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6570             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6571           } else {
6572             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6573             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6574           }
6575 */
6576         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
6577         size = AOP_SIZE(left);
6578
6579         {
6580           int bp = posbit, ofs=0;
6581           
6582             while(bp > 7) {
6583               bp -= 8;
6584               ofs++;
6585             }
6586         
6587           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6588                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
6589
6590         }
6591 /*
6592           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6593                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6594 */
6595           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6596           
6597           ifx->generated = 1;
6598         }
6599         goto release;
6600       }
6601     } else {
6602       symbol *tlbl = newiTempLabel(NULL);
6603       int sizel = AOP_SIZE(left);
6604       if(size)
6605         pic16_emitcode("setb","c");
6606       while(sizel--){
6607         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6608           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6609           // byte ==  2^n ?
6610           if((posbit = isLiteralBit(bytelit)) != 0)
6611             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6612           else{
6613             if(bytelit != 0x0FFL)
6614               pic16_emitcode("anl","a,%s",
6615                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6616             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6617           }
6618         }
6619         offset++;
6620       }
6621       // bit = left & literal
6622       if(size){
6623         pic16_emitcode("clr","c");
6624         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6625       }
6626       // if(left & literal)
6627       else{
6628         if(ifx)
6629           jmpTrueOrFalse(ifx, tlbl);
6630         goto release ;
6631       }
6632     }
6633     pic16_outBitC(result);
6634     goto release ;
6635   }
6636
6637   /* if left is same as result */
6638   if(pic16_sameRegs(AOP(result),AOP(left))){
6639     int know_W = -1;
6640     for(;size--; offset++,lit>>=8) {
6641       if(AOP_TYPE(right) == AOP_LIT){
6642         switch(lit & 0xff) {
6643         case 0x00:
6644           /*  and'ing with 0 has clears the result */
6645 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6646           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6647           break;
6648         case 0xff:
6649           /* and'ing with 0xff is a nop when the result and left are the same */
6650           break;
6651
6652         default:
6653           {
6654             int p = my_powof2( (~lit) & 0xff );
6655             if(p>=0) {
6656               /* only one bit is set in the literal, so use a bcf instruction */
6657 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6658               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6659
6660             } else {
6661               pic16_emitcode("movlw","0x%x", (lit & 0xff));
6662               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6663               if(know_W != (lit&0xff))
6664                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6665               know_W = lit &0xff;
6666               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6667             }
6668           }    
6669         }
6670       } else {
6671         if (AOP_TYPE(left) == AOP_ACC) {
6672           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6673         } else {                    
6674           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6675           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6676
6677         }
6678       }
6679     }
6680
6681   } else {
6682     // left & result in different registers
6683     if(AOP_TYPE(result) == AOP_CRY){
6684       // result = bit
6685       // if(size), result in bit
6686       // if(!size && ifx), conditional oper: if(left & right)
6687       symbol *tlbl = newiTempLabel(NULL);
6688       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6689       if(size)
6690         pic16_emitcode("setb","c");
6691       while(sizer--){
6692         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6693         pic16_emitcode("anl","a,%s",
6694                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6695         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6696         offset++;
6697       }
6698       if(size){
6699         CLRC;
6700         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6701         pic16_outBitC(result);
6702       } else if(ifx)
6703         jmpTrueOrFalse(ifx, tlbl);
6704     } else {
6705       for(;(size--);offset++) {
6706         // normal case
6707         // result = left & right
6708         if(AOP_TYPE(right) == AOP_LIT){
6709           int t = (lit >> (offset*8)) & 0x0FFL;
6710           switch(t) { 
6711           case 0x00:
6712             pic16_emitcode("clrf","%s",
6713                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6714             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6715             break;
6716           case 0xff:
6717             pic16_emitcode("movf","%s,w",
6718                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6719             pic16_emitcode("movwf","%s",
6720                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6721             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6722             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6723             break;
6724           default:
6725             pic16_emitcode("movlw","0x%x",t);
6726             pic16_emitcode("andwf","%s,w",
6727                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6728             pic16_emitcode("movwf","%s",
6729                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6730               
6731             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6732             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6733             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6734           }
6735           continue;
6736         }
6737
6738         if (AOP_TYPE(left) == AOP_ACC) {
6739           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6740           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6741         } else {
6742           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6743           pic16_emitcode("andwf","%s,w",
6744                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6745           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6746           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6747         }
6748         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6749         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6750       }
6751     }
6752   }
6753
6754   release :
6755     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6756   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6757   pic16_freeAsmop(result,NULL,ic,TRUE);     
6758 }
6759
6760 /*-----------------------------------------------------------------*/
6761 /* genOr  - code for or                                            */
6762 /*-----------------------------------------------------------------*/
6763 static void genOr (iCode *ic, iCode *ifx)
6764 {
6765     operand *left, *right, *result;
6766     int size, offset=0;
6767     unsigned long lit = 0L;
6768
6769     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6770
6771     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6772     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6773     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6774
6775     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6776
6777     /* if left is a literal & right is not then exchange them */
6778     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6779         AOP_NEEDSACC(left)) {
6780         operand *tmp = right ;
6781         right = left;
6782         left = tmp;
6783     }
6784
6785     /* if result = right then exchange them */
6786     if(pic16_sameRegs(AOP(result),AOP(right))){
6787         operand *tmp = right ;
6788         right = left;
6789         left = tmp;
6790     }
6791
6792     /* if right is bit then exchange them */
6793     if (AOP_TYPE(right) == AOP_CRY &&
6794         AOP_TYPE(left) != AOP_CRY){
6795         operand *tmp = right ;
6796         right = left;
6797         left = tmp;
6798     }
6799
6800     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6801
6802     if(AOP_TYPE(right) == AOP_LIT)
6803         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6804
6805     size = AOP_SIZE(result);
6806
6807     // if(bit | yy)
6808     // xx = bit | yy;
6809     if (AOP_TYPE(left) == AOP_CRY){
6810         if(AOP_TYPE(right) == AOP_LIT){
6811             // c = bit & literal;
6812             if(lit){
6813                 // lit != 0 => result = 1
6814                 if(AOP_TYPE(result) == AOP_CRY){
6815                   if(size)
6816                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6817                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6818                   //     AOP(result)->aopu.aop_dir,
6819                   //     AOP(result)->aopu.aop_dir);
6820                     else if(ifx)
6821                         continueIfTrue(ifx);
6822                     goto release;
6823                 }
6824             } else {
6825                 // lit == 0 => result = left
6826                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6827                     goto release;
6828                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6829             }
6830         } else {
6831             if (AOP_TYPE(right) == AOP_CRY){
6832               if(pic16_sameRegs(AOP(result),AOP(left))){
6833                 // c = bit | bit;
6834                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6835                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6836                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6837
6838                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6839                          AOP(result)->aopu.aop_dir,
6840                          AOP(result)->aopu.aop_dir);
6841                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6842                          AOP(right)->aopu.aop_dir,
6843                          AOP(right)->aopu.aop_dir);
6844                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6845                          AOP(result)->aopu.aop_dir,
6846                          AOP(result)->aopu.aop_dir);
6847               } else {
6848                 if( AOP_TYPE(result) == AOP_ACC) {
6849                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6850                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6851                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6852                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6853
6854                 } else {
6855
6856                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6857                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6858                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6859                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6860
6861                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6862                                  AOP(result)->aopu.aop_dir,
6863                                  AOP(result)->aopu.aop_dir);
6864                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6865                                  AOP(right)->aopu.aop_dir,
6866                                  AOP(right)->aopu.aop_dir);
6867                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6868                                  AOP(left)->aopu.aop_dir,
6869                                  AOP(left)->aopu.aop_dir);
6870                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6871                                  AOP(result)->aopu.aop_dir,
6872                                  AOP(result)->aopu.aop_dir);
6873                 }
6874               }
6875             } else {
6876                 // c = bit | val;
6877                 symbol *tlbl = newiTempLabel(NULL);
6878                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6879
6880
6881                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6882                 if( AOP_TYPE(right) == AOP_ACC) {
6883                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6884                   emitSKPNZ;
6885                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6886                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6887                 }
6888
6889
6890
6891                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6892                     pic16_emitcode(";XXX setb","c");
6893                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6894                          AOP(left)->aopu.aop_dir,tlbl->key+100);
6895                 pic16_toBoolean(right);
6896                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6897                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6898                     jmpTrueOrFalse(ifx, tlbl);
6899                     goto release;
6900                 } else {
6901                     CLRC;
6902                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6903                 }
6904             }
6905         }
6906         // bit = c
6907         // val = c
6908         if(size)
6909             pic16_outBitC(result);
6910         // if(bit | ...)
6911         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6912             genIfxJump(ifx, "c");           
6913         goto release ;
6914     }
6915
6916     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6917     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6918     if((AOP_TYPE(right) == AOP_LIT) &&
6919        (AOP_TYPE(result) == AOP_CRY) &&
6920        (AOP_TYPE(left) != AOP_CRY)){
6921         if(lit){
6922           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6923             // result = 1
6924             if(size)
6925                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6926             else 
6927                 continueIfTrue(ifx);
6928             goto release;
6929         } else {
6930           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6931             // lit = 0, result = boolean(left)
6932             if(size)
6933                 pic16_emitcode(";XXX setb","c");
6934             pic16_toBoolean(right);
6935             if(size){
6936                 symbol *tlbl = newiTempLabel(NULL);
6937                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6938                 CLRC;
6939                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6940             } else {
6941                 genIfxJump (ifx,"a");
6942                 goto release;
6943             }
6944         }
6945         pic16_outBitC(result);
6946         goto release ;
6947     }
6948
6949     /* if left is same as result */
6950     if(pic16_sameRegs(AOP(result),AOP(left))){
6951       int know_W = -1;
6952       for(;size--; offset++,lit>>=8) {
6953         if(AOP_TYPE(right) == AOP_LIT){
6954           if((lit & 0xff) == 0)
6955             /*  or'ing with 0 has no effect */
6956             continue;
6957           else {
6958             int p = my_powof2(lit & 0xff);
6959             if(p>=0) {
6960               /* only one bit is set in the literal, so use a bsf instruction */
6961               pic16_emitpcode(POC_BSF,
6962                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6963             } else {
6964               if(know_W != (lit & 0xff))
6965                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6966               know_W = lit & 0xff;
6967               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6968             }
6969                     
6970           }
6971         } else {
6972           if (AOP_TYPE(left) == AOP_ACC) {
6973             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
6974             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6975           } else {                  
6976             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6977             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
6978
6979             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6980             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6981
6982           }
6983         }
6984       }
6985     } else {
6986         // left & result in different registers
6987         if(AOP_TYPE(result) == AOP_CRY){
6988             // result = bit
6989             // if(size), result in bit
6990             // if(!size && ifx), conditional oper: if(left | right)
6991             symbol *tlbl = newiTempLabel(NULL);
6992             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6993             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6994
6995
6996             if(size)
6997                 pic16_emitcode(";XXX setb","c");
6998             while(sizer--){
6999                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7000                 pic16_emitcode(";XXX orl","a,%s",
7001                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7002                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7003                 offset++;
7004             }
7005             if(size){
7006                 CLRC;
7007                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7008                 pic16_outBitC(result);
7009             } else if(ifx)
7010                 jmpTrueOrFalse(ifx, tlbl);
7011         } else for(;(size--);offset++){
7012           // normal case
7013           // result = left & right
7014           if(AOP_TYPE(right) == AOP_LIT){
7015             int t = (lit >> (offset*8)) & 0x0FFL;
7016             switch(t) { 
7017             case 0x00:
7018               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7019               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7020
7021               pic16_emitcode("movf","%s,w",
7022                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7023               pic16_emitcode("movwf","%s",
7024                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7025               break;
7026             default:
7027               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7028               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7029               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7030
7031               pic16_emitcode("movlw","0x%x",t);
7032               pic16_emitcode("iorwf","%s,w",
7033                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7034               pic16_emitcode("movwf","%s",
7035                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7036               
7037             }
7038             continue;
7039           }
7040
7041           // faster than result <- left, anl result,right
7042           // and better if result is SFR
7043           if (AOP_TYPE(left) == AOP_ACC) {
7044             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7045             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7046           } else {
7047             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7048             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7049
7050             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7051             pic16_emitcode("iorwf","%s,w",
7052                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7053           }
7054           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7055           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7056         }
7057     }
7058
7059 release :
7060     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7061     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7062     pic16_freeAsmop(result,NULL,ic,TRUE);     
7063 }
7064
7065 /*-----------------------------------------------------------------*/
7066 /* genXor - code for xclusive or                                   */
7067 /*-----------------------------------------------------------------*/
7068 static void genXor (iCode *ic, iCode *ifx)
7069 {
7070   operand *left, *right, *result;
7071   int size, offset=0;
7072   unsigned long lit = 0L;
7073
7074   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7075
7076   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7077   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7078   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7079
7080   /* if left is a literal & right is not ||
7081      if left needs acc & right does not */
7082   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7083       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7084     operand *tmp = right ;
7085     right = left;
7086     left = tmp;
7087   }
7088
7089   /* if result = right then exchange them */
7090   if(pic16_sameRegs(AOP(result),AOP(right))){
7091     operand *tmp = right ;
7092     right = left;
7093     left = tmp;
7094   }
7095
7096   /* if right is bit then exchange them */
7097   if (AOP_TYPE(right) == AOP_CRY &&
7098       AOP_TYPE(left) != AOP_CRY){
7099     operand *tmp = right ;
7100     right = left;
7101     left = tmp;
7102   }
7103   if(AOP_TYPE(right) == AOP_LIT)
7104     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7105
7106   size = AOP_SIZE(result);
7107
7108   // if(bit ^ yy)
7109   // xx = bit ^ yy;
7110   if (AOP_TYPE(left) == AOP_CRY){
7111     if(AOP_TYPE(right) == AOP_LIT){
7112       // c = bit & literal;
7113       if(lit>>1){
7114         // lit>>1  != 0 => result = 1
7115         if(AOP_TYPE(result) == AOP_CRY){
7116           if(size)
7117             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
7118             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7119           else if(ifx)
7120             continueIfTrue(ifx);
7121           goto release;
7122         }
7123         pic16_emitcode("setb","c");
7124       } else{
7125         // lit == (0 or 1)
7126         if(lit == 0){
7127           // lit == 0, result = left
7128           if(size && pic16_sameRegs(AOP(result),AOP(left)))
7129             goto release;
7130           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7131         } else{
7132           // lit == 1, result = not(left)
7133           if(size && pic16_sameRegs(AOP(result),AOP(left))){
7134             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
7135             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
7136             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7137             goto release;
7138           } else {
7139             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7140             pic16_emitcode("cpl","c");
7141           }
7142         }
7143       }
7144
7145     } else {
7146       // right != literal
7147       symbol *tlbl = newiTempLabel(NULL);
7148       if (AOP_TYPE(right) == AOP_CRY){
7149         // c = bit ^ bit;
7150         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7151       }
7152       else{
7153         int sizer = AOP_SIZE(right);
7154         // c = bit ^ val
7155         // if val>>1 != 0, result = 1
7156         pic16_emitcode("setb","c");
7157         while(sizer){
7158           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
7159           if(sizer == 1)
7160             // test the msb of the lsb
7161             pic16_emitcode("anl","a,#0xfe");
7162           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7163           sizer--;
7164         }
7165         // val = (0,1)
7166         pic16_emitcode("rrc","a");
7167       }
7168       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
7169       pic16_emitcode("cpl","c");
7170       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
7171     }
7172     // bit = c
7173     // val = c
7174     if(size)
7175       pic16_outBitC(result);
7176     // if(bit | ...)
7177     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7178       genIfxJump(ifx, "c");           
7179     goto release ;
7180   }
7181
7182   if(pic16_sameRegs(AOP(result),AOP(left))){
7183     /* if left is same as result */
7184     for(;size--; offset++) {
7185       if(AOP_TYPE(right) == AOP_LIT){
7186         int t  = (lit >> (offset*8)) & 0x0FFL;
7187         if(t == 0x00L)
7188           continue;
7189         else
7190           if (IS_AOP_PREG(left)) {
7191             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7192             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7193             pic16_aopPut(AOP(result),"a",offset);
7194           } else {
7195             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7196             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7197             pic16_emitcode("xrl","%s,%s",
7198                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7199                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7200           }
7201       } else {
7202         if (AOP_TYPE(left) == AOP_ACC)
7203           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7204         else {
7205           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7206           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7207 /*
7208           if (IS_AOP_PREG(left)) {
7209             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7210             pic16_aopPut(AOP(result),"a",offset);
7211           } else
7212             pic16_emitcode("xrl","%s,a",
7213                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7214 */
7215         }
7216       }
7217     }
7218   } else {
7219     // left & result in different registers
7220     if(AOP_TYPE(result) == AOP_CRY){
7221       // result = bit
7222       // if(size), result in bit
7223       // if(!size && ifx), conditional oper: if(left ^ right)
7224       symbol *tlbl = newiTempLabel(NULL);
7225       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7226       if(size)
7227         pic16_emitcode("setb","c");
7228       while(sizer--){
7229         if((AOP_TYPE(right) == AOP_LIT) &&
7230            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7231           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7232         } else {
7233           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7234           pic16_emitcode("xrl","a,%s",
7235                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7236         }
7237         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7238         offset++;
7239       }
7240       if(size){
7241         CLRC;
7242         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7243         pic16_outBitC(result);
7244       } else if(ifx)
7245         jmpTrueOrFalse(ifx, tlbl);
7246     } else for(;(size--);offset++){
7247       // normal case
7248       // result = left & right
7249       if(AOP_TYPE(right) == AOP_LIT){
7250         int t = (lit >> (offset*8)) & 0x0FFL;
7251         switch(t) { 
7252         case 0x00:
7253           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7254           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7255           pic16_emitcode("movf","%s,w",
7256                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7257           pic16_emitcode("movwf","%s",
7258                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7259           break;
7260         case 0xff:
7261           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7262           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7263           pic16_emitcode("comf","%s,w",
7264                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7265           pic16_emitcode("movwf","%s",
7266                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7267           break;
7268         default:
7269           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7270           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7271           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7272           pic16_emitcode("movlw","0x%x",t);
7273           pic16_emitcode("xorwf","%s,w",
7274                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7275           pic16_emitcode("movwf","%s",
7276                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7277
7278         }
7279         continue;
7280       }
7281
7282       // faster than result <- left, anl result,right
7283       // and better if result is SFR
7284       if (AOP_TYPE(left) == AOP_ACC) {
7285         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7286         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7287       } else {
7288         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7289         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7290         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7291         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7292       }
7293       if ( AOP_TYPE(result) != AOP_ACC){
7294         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7295         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7296       }
7297     }
7298   }
7299
7300   release :
7301     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7302   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7303   pic16_freeAsmop(result,NULL,ic,TRUE);     
7304 }
7305
7306 /*-----------------------------------------------------------------*/
7307 /* genInline - write the inline code out                           */
7308 /*-----------------------------------------------------------------*/
7309 static void genInline (iCode *ic)
7310 {
7311   char *buffer, *bp, *bp1;
7312     
7313         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7314
7315         _G.inLine += (!options.asmpeep);
7316
7317         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7318         strcpy(buffer,IC_INLINE(ic));
7319
7320 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7321
7322         /* emit each line as a code */
7323         while (*bp) {
7324                 if (*bp == '\n') {
7325                         *bp++ = '\0';
7326
7327                         if(*bp1)
7328                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7329                         bp1 = bp;
7330                 } else {
7331                         if (*bp == ':') {
7332                                 bp++;
7333                                 *bp = '\0';
7334                                 bp++;
7335
7336                                 /* print label, use this special format with NULL directive
7337                                  * to denote that the argument should not be indented with tab */
7338                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7339                                 bp1 = bp;
7340                         } else
7341                                 bp++;
7342                 }
7343         }
7344
7345         if ((bp1 != bp) && *bp1)
7346                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7347
7348
7349     Safe_free(buffer);
7350
7351     _G.inLine -= (!options.asmpeep);
7352 }
7353
7354 /*-----------------------------------------------------------------*/
7355 /* genRRC - rotate right with carry                                */
7356 /*-----------------------------------------------------------------*/
7357 static void genRRC (iCode *ic)
7358 {
7359   operand *left , *result ;
7360   int size, offset = 0, same;
7361
7362   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7363
7364   /* rotate right with carry */
7365   left = IC_LEFT(ic);
7366   result=IC_RESULT(ic);
7367   pic16_aopOp (left,ic,FALSE);
7368   pic16_aopOp (result,ic,FALSE);
7369
7370   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7371
7372   same = pic16_sameRegs(AOP(result),AOP(left));
7373
7374   size = AOP_SIZE(result);    
7375
7376   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7377
7378   /* get the lsb and put it into the carry */
7379   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7380
7381   offset = 0 ;
7382
7383   while(size--) {
7384
7385     if(same) {
7386       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7387     } else {
7388       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7389       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7390     }
7391
7392     offset++;
7393   }
7394
7395   pic16_freeAsmop(left,NULL,ic,TRUE);
7396   pic16_freeAsmop(result,NULL,ic,TRUE);
7397 }
7398
7399 /*-----------------------------------------------------------------*/
7400 /* genRLC - generate code for rotate left with carry               */
7401 /*-----------------------------------------------------------------*/
7402 static void genRLC (iCode *ic)
7403 {    
7404   operand *left , *result ;
7405   int size, offset = 0;
7406   int same;
7407
7408   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7409   /* rotate right with carry */
7410   left = IC_LEFT(ic);
7411   result=IC_RESULT(ic);
7412   pic16_aopOp (left,ic,FALSE);
7413   pic16_aopOp (result,ic,FALSE);
7414
7415   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7416
7417   same = pic16_sameRegs(AOP(result),AOP(left));
7418
7419   /* move it to the result */
7420   size = AOP_SIZE(result);    
7421
7422   /* get the msb and put it into the carry */
7423   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7424
7425   offset = 0 ;
7426
7427   while(size--) {
7428
7429     if(same) {
7430       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7431     } else {
7432       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7433       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7434     }
7435
7436     offset++;
7437   }
7438
7439
7440   pic16_freeAsmop(left,NULL,ic,TRUE);
7441   pic16_freeAsmop(result,NULL,ic,TRUE);
7442 }
7443
7444
7445 /* gpasm can get the highest order bit with HIGH/UPPER
7446  * so the following probably is not needed -- VR */
7447  
7448 /*-----------------------------------------------------------------*/
7449 /* genGetHbit - generates code get highest order bit               */
7450 /*-----------------------------------------------------------------*/
7451 static void genGetHbit (iCode *ic)
7452 {
7453     operand *left, *result;
7454     left = IC_LEFT(ic);
7455     result=IC_RESULT(ic);
7456     pic16_aopOp (left,ic,FALSE);
7457     pic16_aopOp (result,ic,FALSE);
7458
7459     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7460     /* get the highest order byte into a */
7461     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7462     if(AOP_TYPE(result) == AOP_CRY){
7463         pic16_emitcode("rlc","a");
7464         pic16_outBitC(result);
7465     }
7466     else{
7467         pic16_emitcode("rl","a");
7468         pic16_emitcode("anl","a,#0x01");
7469         pic16_outAcc(result);
7470     }
7471
7472
7473     pic16_freeAsmop(left,NULL,ic,TRUE);
7474     pic16_freeAsmop(result,NULL,ic,TRUE);
7475 }
7476
7477 #if 0
7478 /*-----------------------------------------------------------------*/
7479 /* AccRol - rotate left accumulator by known count                 */
7480 /*-----------------------------------------------------------------*/
7481 static void AccRol (int shCount)
7482 {
7483     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7484     shCount &= 0x0007;              // shCount : 0..7
7485     switch(shCount){
7486         case 0 :
7487             break;
7488         case 1 :
7489             pic16_emitcode("rl","a");
7490             break;
7491         case 2 :
7492             pic16_emitcode("rl","a");
7493             pic16_emitcode("rl","a");
7494             break;
7495         case 3 :
7496             pic16_emitcode("swap","a");
7497             pic16_emitcode("rr","a");
7498             break;
7499         case 4 :
7500             pic16_emitcode("swap","a");
7501             break;
7502         case 5 :
7503             pic16_emitcode("swap","a");
7504             pic16_emitcode("rl","a");
7505             break;
7506         case 6 :
7507             pic16_emitcode("rr","a");
7508             pic16_emitcode("rr","a");
7509             break;
7510         case 7 :
7511             pic16_emitcode("rr","a");
7512             break;
7513     }
7514 }
7515 #endif
7516
7517 /*-----------------------------------------------------------------*/
7518 /* AccLsh - left shift accumulator by known count                  */
7519 /*-----------------------------------------------------------------*/
7520 static void AccLsh (int shCount)
7521 {
7522         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7523         switch(shCount){
7524                 case 0 :
7525                         return;
7526                         break;
7527                 case 1 :
7528                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7529                         break;
7530                 case 2 :
7531                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7532                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7533                         break;
7534                 case 3 :
7535                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7536                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7537                         break;
7538                 case 4 :
7539                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7540                         break;
7541                 case 5 :
7542                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7543                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7544                         break;
7545                 case 6 :
7546                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7547                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7548                         break;
7549                 case 7 :
7550                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7551                         break;
7552         }
7553
7554         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7555 }
7556
7557 /*-----------------------------------------------------------------*/
7558 /* AccRsh - right shift accumulator by known count                 */
7559 /*-----------------------------------------------------------------*/
7560 static void AccRsh (int shCount, int andmask)
7561 {
7562         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7563         switch(shCount){
7564                 case 0 :
7565                         return; break;
7566                 case 1 :
7567                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7568 //                      andmask = 0;    /* no need */
7569                         break;
7570                 case 2 :
7571                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7572                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7573 //                      andmask = 0;    /* no need */
7574                         break;
7575                 case 3 :
7576                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7577                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7578                         break;
7579                 case 4 :
7580                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7581                         break;
7582                 case 5 :
7583                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7584                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7585                         break;
7586                 case 6 :
7587                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7588                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7589                         break;
7590                 case 7 :
7591                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7592                         break;
7593         }
7594         
7595         if(andmask)
7596                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7597         else
7598                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7599 }
7600
7601 #if 0
7602 /*-----------------------------------------------------------------*/
7603 /* AccSRsh - signed right shift accumulator by known count                 */
7604 /*-----------------------------------------------------------------*/
7605 static void AccSRsh (int shCount)
7606 {
7607     symbol *tlbl ;
7608     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7609     if(shCount != 0){
7610         if(shCount == 1){
7611             pic16_emitcode("mov","c,acc.7");
7612             pic16_emitcode("rrc","a");
7613         } else if(shCount == 2){
7614             pic16_emitcode("mov","c,acc.7");
7615             pic16_emitcode("rrc","a");
7616             pic16_emitcode("mov","c,acc.7");
7617             pic16_emitcode("rrc","a");
7618         } else {
7619             tlbl = newiTempLabel(NULL);
7620             /* rotate right accumulator */
7621             AccRol(8 - shCount);
7622             /* and kill the higher order bits */
7623             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7624             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7625             pic16_emitcode("orl","a,#0x%02x",
7626                      (unsigned char)~SRMask[shCount]);
7627             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7628         }
7629     }
7630 }
7631 #endif
7632 /*-----------------------------------------------------------------*/
7633 /* shiftR1Left2Result - shift right one byte from left to result   */
7634 /*-----------------------------------------------------------------*/
7635 static void shiftR1Left2ResultSigned (operand *left, int offl,
7636                                 operand *result, int offr,
7637                                 int shCount)
7638 {
7639   int same;
7640
7641   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7642
7643   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7644
7645   switch(shCount) {
7646   case 1:
7647     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7648     if(same) 
7649       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7650     else {
7651       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7652       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7653     }
7654
7655     break;
7656   case 2:
7657
7658     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7659     if(same) 
7660       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7661     else {
7662       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7663       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7664     }
7665     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7666     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7667
7668     break;
7669
7670   case 3:
7671     if(same)
7672       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7673     else {
7674       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7675       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7676     }
7677
7678     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7679     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7680     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7681
7682     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7683     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7684
7685     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7686     break;
7687
7688   case 4:
7689     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7690     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
7691     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7692     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
7693     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7694     break;
7695   case 5:
7696     if(same) {
7697       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
7698     } else {
7699       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
7700       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7701     }
7702     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
7703     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
7704     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7705     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
7706     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7707     break;
7708
7709   case 6:
7710     if(same) {
7711       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7712       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7713       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7714       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7715       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7716       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7717     } else {
7718       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7719       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7720       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7721       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7722       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7723     }
7724     break;
7725
7726   case 7:
7727     if(same) {
7728       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7729       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7730       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7731       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7732     } else {
7733       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7734       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7735       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7736     }
7737
7738   default:
7739     break;
7740   }
7741 }
7742
7743 /*-----------------------------------------------------------------*/
7744 /* shiftR1Left2Result - shift right one byte from left to result   */
7745 /*-----------------------------------------------------------------*/
7746 static void shiftR1Left2Result (operand *left, int offl,
7747                                 operand *result, int offr,
7748                                 int shCount, int sign)
7749 {
7750   int same;
7751
7752   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7753
7754   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7755
7756   /* Copy the msb into the carry if signed. */
7757   if(sign) {
7758     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7759     return;
7760   }
7761
7762
7763
7764   switch(shCount) {
7765   case 1:
7766     emitCLRC;
7767     if(same) 
7768       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7769     else {
7770       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7771       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7772     }
7773     break;
7774   case 2:
7775     emitCLRC;
7776     if(same) {
7777       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7778     } else {
7779       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7780       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7781     }
7782     emitCLRC;
7783     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7784
7785     break;
7786   case 3:
7787     if(same)
7788       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7789     else {
7790       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7791       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7792     }
7793
7794     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7795     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7796     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7797     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7798     break;
7799       
7800   case 4:
7801     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7802     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7803     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7804     break;
7805
7806   case 5:
7807     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7808     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7809     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7810     emitCLRC;
7811     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7812
7813     break;
7814   case 6:
7815
7816     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
7817     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7818     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7819     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7820     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7821     break;
7822
7823   case 7:
7824
7825     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7826     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7827     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7828
7829     break;
7830
7831   default:
7832     break;
7833   }
7834 }
7835
7836 /*-----------------------------------------------------------------*/
7837 /* shiftL1Left2Result - shift left one byte from left to result    */
7838 /*-----------------------------------------------------------------*/
7839 static void shiftL1Left2Result (operand *left, int offl,
7840                                 operand *result, int offr, int shCount)
7841 {
7842   int same;
7843
7844   //    char *l;
7845   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7846
7847   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7848   DEBUGpic16_emitcode ("; ***","same =  %d",same);
7849     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7850     //    MOVA(l);
7851     /* shift left accumulator */
7852     //AccLsh(shCount); // don't comment out just yet...
7853   //    pic16_aopPut(AOP(result),"a",offr);
7854
7855   switch(shCount) {
7856   case 1:
7857     /* Shift left 1 bit position */
7858     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7859     if(same) {
7860       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7861     } else {
7862       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7863       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7864     }
7865     break;
7866   case 2:
7867     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7868     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7869     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7870     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7871     break;
7872   case 3:
7873     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7874     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7875     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7876     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7877     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7878     break;
7879   case 4:
7880     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7881     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7882     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7883     break;
7884   case 5:
7885     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7886     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7887     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7888     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7889     break;
7890   case 6:
7891     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7892     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7893     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7894     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7895     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7896     break;
7897   case 7:
7898     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7899     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7900     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7901     break;
7902
7903   default:
7904     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7905   }
7906
7907 }
7908
7909 /*-----------------------------------------------------------------*/
7910 /* movLeft2Result - move byte from left to result                  */
7911 /*-----------------------------------------------------------------*/
7912 static void movLeft2Result (operand *left, int offl,
7913                             operand *result, int offr)
7914 {
7915   char *l;
7916   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7917   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7918     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7919
7920     if (*l == '@' && (IS_AOP_PREG(result))) {
7921       pic16_emitcode("mov","a,%s",l);
7922       pic16_aopPut(AOP(result),"a",offr);
7923     } else {
7924       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7925       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7926     }
7927   }
7928 }
7929
7930 /*-----------------------------------------------------------------*/
7931 /* shiftL2Left2Result - shift left two bytes from left to result   */
7932 /*-----------------------------------------------------------------*/
7933 static void shiftL2Left2Result (operand *left, int offl,
7934                                 operand *result, int offr, int shCount)
7935 {
7936   int same = pic16_sameRegs(AOP(result), AOP(left));
7937   int i;
7938
7939   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7940
7941   if (same && (offl != offr)) { // shift bytes
7942     if (offr > offl) {
7943        for(i=1;i>-1;i--) {
7944          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7945          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7946        }
7947     } else { // just treat as different later on
7948                 same = 0;
7949     }
7950   }
7951
7952   if(same) {
7953     switch(shCount) {
7954     case 0:
7955       break;
7956     case 1:
7957     case 2:
7958     case 3:
7959
7960       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7961       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7962       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7963
7964       while(--shCount) {
7965                 emitCLRC;
7966                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7967                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7968       }
7969
7970       break;
7971     case 4:
7972     case 5:
7973       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7974       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7975       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7976       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7977       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7978       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7979       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7980       if(shCount >=5) {
7981                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7982                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7983       }
7984       break;
7985     case 6:
7986       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7987       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7988       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7989       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7990       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7991       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7992       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7993       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7994       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7995       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7996       break;
7997     case 7:
7998       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7999       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8000       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8001       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8002       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8003     }
8004
8005   } else {
8006     switch(shCount) {
8007     case 0:
8008       break;
8009     case 1:
8010     case 2:
8011     case 3:
8012       /* note, use a mov/add for the shift since the mov has a
8013          chance of getting optimized out */
8014       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8015       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8016       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8017       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8018       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8019
8020       while(--shCount) {
8021                 emitCLRC;
8022                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8023                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8024       }
8025       break;
8026
8027     case 4:
8028     case 5:
8029       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8030       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8031       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8032       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8033       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8034       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8035       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8036       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8037
8038
8039       if(shCount == 5) {
8040                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8041                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8042       }
8043       break;
8044     case 6:
8045       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8046       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8047       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8048       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8049
8050       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8051       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8052       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8053       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8054       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8055       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8056       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8057       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8058       break;
8059     case 7:
8060       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8061       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8062       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8063       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8064       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8065     }
8066   }
8067
8068 }
8069 /*-----------------------------------------------------------------*/
8070 /* shiftR2Left2Result - shift right two bytes from left to result  */
8071 /*-----------------------------------------------------------------*/
8072 static void shiftR2Left2Result (operand *left, int offl,
8073                                 operand *result, int offr,
8074                                 int shCount, int sign)
8075 {
8076   int same = pic16_sameRegs(AOP(result), AOP(left));
8077   int i;
8078   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8079
8080   if (same && (offl != offr)) { // shift right bytes
8081     if (offr < offl) {
8082        for(i=0;i<2;i++) {
8083          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8084          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8085        }
8086     } else { // just treat as different later on
8087                 same = 0;
8088     }
8089   }
8090
8091   switch(shCount) {
8092   case 0:
8093     break;
8094   case 1:
8095   case 2:
8096   case 3:
8097     if(sign)
8098       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8099     else
8100       emitCLRC;
8101
8102     if(same) {
8103       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8104       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8105     } else {
8106       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8107       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8108       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8109       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8110     }
8111
8112     while(--shCount) {
8113       if(sign)
8114                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8115       else
8116                 emitCLRC;
8117       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8118       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8119     }
8120     break;
8121   case 4:
8122   case 5:
8123     if(same) {
8124
8125       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
8126       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
8127       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8128
8129       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8130       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
8131       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8132       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8133     } else {
8134       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8135       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8136       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8137
8138       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8139       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8140       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8141       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8142       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8143     }
8144
8145     if(shCount >=5) {
8146       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8147       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8148     }
8149
8150     if(sign) {
8151       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
8152       pic16_emitpcode(POC_BTFSC, 
8153                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
8154       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8155     }
8156
8157     break;
8158
8159   case 6:
8160     if(same) {
8161
8162       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8163       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8164
8165       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8166       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8167       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8168       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8169       if(sign) {
8170         pic16_emitpcode(POC_BTFSC, 
8171                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8172         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8173       }
8174       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8175       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
8176       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8177       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8178     } else {
8179       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8180       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8181       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8182       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8183       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8184       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8185       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8186       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8187       if(sign) {
8188         pic16_emitpcode(POC_BTFSC, 
8189                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8190         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8191       }
8192       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8193       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8194
8195         
8196     }
8197
8198     break;
8199   case 7:
8200     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8201     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8202     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8203     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8204     if(sign) {
8205       emitSKPNC;
8206       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8207     } else 
8208       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8209   }
8210 }
8211
8212
8213 /*-----------------------------------------------------------------*/
8214 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8215 /*-----------------------------------------------------------------*/
8216 static void shiftLLeftOrResult (operand *left, int offl,
8217                                 operand *result, int offr, int shCount)
8218 {
8219     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8220
8221     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8222     /* shift left accumulator */
8223     AccLsh(shCount);
8224     /* or with result */
8225     /* back to result */
8226     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8227 }
8228
8229 /*-----------------------------------------------------------------*/
8230 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8231 /*-----------------------------------------------------------------*/
8232 static void shiftRLeftOrResult (operand *left, int offl,
8233                                 operand *result, int offr, int shCount)
8234 {
8235     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8236     
8237     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8238     /* shift right accumulator */
8239     AccRsh(shCount, 1);
8240     /* or with result */
8241     /* back to result */
8242     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8243 }
8244
8245 /*-----------------------------------------------------------------*/
8246 /* genlshOne - left shift a one byte quantity by known count       */
8247 /*-----------------------------------------------------------------*/
8248 static void genlshOne (operand *result, operand *left, int shCount)
8249 {       
8250     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8251     shiftL1Left2Result(left, LSB, result, LSB, shCount);
8252 }
8253
8254 /*-----------------------------------------------------------------*/
8255 /* genlshTwo - left shift two bytes by known amount != 0           */
8256 /*-----------------------------------------------------------------*/
8257 static void genlshTwo (operand *result,operand *left, int shCount)
8258 {
8259     int size;
8260     
8261     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8262     size = pic16_getDataSize(result);
8263
8264     /* if shCount >= 8 */
8265     if (shCount >= 8) {
8266         shCount -= 8 ;
8267
8268         if (size > 1){
8269             if (shCount)
8270                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8271             else 
8272                 movLeft2Result(left, LSB, result, MSB16);
8273         }
8274         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8275     }
8276
8277     /*  1 <= shCount <= 7 */
8278     else {  
8279         if(size == 1)
8280             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
8281         else 
8282             shiftL2Left2Result(left, LSB, result, LSB, shCount);
8283     }
8284 }
8285
8286 /*-----------------------------------------------------------------*/
8287 /* shiftLLong - shift left one long from left to result            */
8288 /* offr = LSB or MSB16                                             */
8289 /*-----------------------------------------------------------------*/
8290 static void shiftLLong (operand *left, operand *result, int offr )
8291 {
8292     int size = AOP_SIZE(result);
8293     int same = pic16_sameRegs(AOP(left),AOP(result));
8294         int i;
8295
8296     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8297
8298         if (same && (offr == MSB16)) { //shift one byte
8299                 for(i=size-1;i>=MSB16;i--) {
8300                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8301                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8302                 }
8303         } else {
8304                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8305         }
8306         
8307     if (size >= LSB+offr ){
8308                 if (same) {
8309                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8310                 } else {
8311                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8312                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8313                 }
8314          }
8315
8316     if(size >= MSB16+offr){
8317                 if (same) {
8318                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8319                 } else {
8320                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8321                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8322                 }
8323     }
8324
8325     if(size >= MSB24+offr){
8326                 if (same) {
8327                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8328                 } else {
8329                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8330                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8331                 }
8332     }
8333
8334     if(size > MSB32+offr){
8335                 if (same) {
8336                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8337                 } else {
8338                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8339                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8340                 }
8341     }
8342     if(offr != LSB)
8343                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8344
8345 }
8346
8347 /*-----------------------------------------------------------------*/
8348 /* genlshFour - shift four byte by a known amount != 0             */
8349 /*-----------------------------------------------------------------*/
8350 static void genlshFour (operand *result, operand *left, int shCount)
8351 {
8352     int size;
8353
8354     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8355     size = AOP_SIZE(result);
8356
8357     /* if shifting more that 3 bytes */
8358     if (shCount >= 24 ) {
8359         shCount -= 24;
8360         if (shCount)
8361             /* lowest order of left goes to the highest
8362             order of the destination */
8363             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8364         else
8365             movLeft2Result(left, LSB, result, MSB32);
8366
8367                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8368                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8369                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8370
8371         return;
8372     }
8373
8374     /* more than two bytes */
8375     else if ( shCount >= 16 ) {
8376         /* lower order two bytes goes to higher order two bytes */
8377         shCount -= 16;
8378         /* if some more remaining */
8379         if (shCount)
8380             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8381         else {
8382             movLeft2Result(left, MSB16, result, MSB32);
8383             movLeft2Result(left, LSB, result, MSB24);
8384         }
8385                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8386                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8387         return;
8388     }    
8389
8390     /* if more than 1 byte */
8391     else if ( shCount >= 8 ) {
8392         /* lower order three bytes goes to higher order  three bytes */
8393         shCount -= 8;
8394         if(size == 2){
8395             if(shCount)
8396                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8397             else
8398                 movLeft2Result(left, LSB, result, MSB16);
8399         }
8400         else{   /* size = 4 */
8401             if(shCount == 0){
8402                 movLeft2Result(left, MSB24, result, MSB32);
8403                 movLeft2Result(left, MSB16, result, MSB24);
8404                 movLeft2Result(left, LSB, result, MSB16);
8405                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8406             }
8407             else if(shCount == 1)
8408                 shiftLLong(left, result, MSB16);
8409             else{
8410                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8411                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8412                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8413                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8414             }
8415         }
8416     }
8417
8418     /* 1 <= shCount <= 7 */
8419     else if(shCount <= 3)
8420     { 
8421         shiftLLong(left, result, LSB);
8422         while(--shCount >= 1)
8423             shiftLLong(result, result, LSB);
8424     }
8425     /* 3 <= shCount <= 7, optimize */
8426     else{
8427         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8428         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8429         shiftL2Left2Result(left, LSB, result, LSB, shCount);
8430     }
8431 }
8432
8433 /*-----------------------------------------------------------------*/
8434 /* genLeftShiftLiteral - left shifting by known count              */
8435 /*-----------------------------------------------------------------*/
8436 static void genLeftShiftLiteral (operand *left,
8437                                  operand *right,
8438                                  operand *result,
8439                                  iCode *ic)
8440 {    
8441     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8442     int size;
8443
8444     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8445     pic16_freeAsmop(right,NULL,ic,TRUE);
8446
8447     pic16_aopOp(left,ic,FALSE);
8448     pic16_aopOp(result,ic,FALSE);
8449
8450     size = getSize(operandType(result));
8451
8452 #if VIEW_SIZE
8453     pic16_emitcode("; shift left ","result %d, left %d",size,
8454              AOP_SIZE(left));
8455 #endif
8456
8457     /* I suppose that the left size >= result size */
8458     if(shCount == 0){
8459         while(size--){
8460             movLeft2Result(left, size, result, size);
8461         }
8462     }
8463
8464     else if(shCount >= (size * 8))
8465         while(size--)
8466             pic16_aopPut(AOP(result),zero,size);
8467     else{
8468         switch (size) {
8469             case 1:
8470                 genlshOne (result,left,shCount);
8471                 break;
8472
8473             case 2:
8474             case 3:
8475                 genlshTwo (result,left,shCount);
8476                 break;
8477
8478             case 4:
8479                 genlshFour (result,left,shCount);
8480                 break;
8481         }
8482     }
8483     pic16_freeAsmop(left,NULL,ic,TRUE);
8484     pic16_freeAsmop(result,NULL,ic,TRUE);
8485 }
8486
8487 /*-----------------------------------------------------------------*
8488  * genMultiAsm - repeat assembly instruction for size of register.
8489  * if endian == 1, then the high byte (i.e base address + size of 
8490  * register) is used first else the low byte is used first;
8491  *-----------------------------------------------------------------*/
8492 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8493 {
8494
8495   int offset = 0;
8496
8497   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8498
8499   if(!reg)
8500     return;
8501
8502   if(!endian) {
8503     endian = 1;
8504   } else {
8505     endian = -1;
8506     offset = size-1;
8507   }
8508
8509   while(size--) {
8510     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
8511     offset += endian;
8512   }
8513
8514 }
8515 /*-----------------------------------------------------------------*/
8516 /* genLeftShift - generates code for left shifting                 */
8517 /*-----------------------------------------------------------------*/
8518 static void genLeftShift (iCode *ic)
8519 {
8520   operand *left,*right, *result;
8521   int size, offset;
8522   char *l;
8523   symbol *tlbl , *tlbl1;
8524   pCodeOp *pctemp;
8525
8526   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8527
8528   right = IC_RIGHT(ic);
8529   left  = IC_LEFT(ic);
8530   result = IC_RESULT(ic);
8531
8532   pic16_aopOp(right,ic,FALSE);
8533
8534   /* if the shift count is known then do it 
8535      as efficiently as possible */
8536   if (AOP_TYPE(right) == AOP_LIT) {
8537     genLeftShiftLiteral (left,right,result,ic);
8538     return ;
8539   }
8540
8541   /* shift count is unknown then we have to form 
8542      a loop get the loop count in B : Note: we take
8543      only the lower order byte since shifting
8544      more that 32 bits make no sense anyway, ( the
8545      largest size of an object can be only 32 bits ) */  
8546
8547     
8548   pic16_aopOp(left,ic,FALSE);
8549   pic16_aopOp(result,ic,FALSE);
8550
8551   /* now move the left to the result if they are not the
8552      same */
8553   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8554       AOP_SIZE(result) > 1) {
8555
8556     size = AOP_SIZE(result);
8557     offset=0;
8558     while (size--) {
8559       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8560       if (*l == '@' && (IS_AOP_PREG(result))) {
8561
8562         pic16_emitcode("mov","a,%s",l);
8563         pic16_aopPut(AOP(result),"a",offset);
8564       } else {
8565         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8566         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8567         //pic16_aopPut(AOP(result),l,offset);
8568       }
8569       offset++;
8570     }
8571   }
8572
8573   size = AOP_SIZE(result);
8574
8575   /* if it is only one byte then */
8576   if (size == 1) {
8577     if(optimized_for_speed) {
8578       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8579       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
8580       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
8581       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8582       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8583       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8584       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8585       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
8586       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
8587       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
8588       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8589       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8590     } else {
8591
8592       tlbl = newiTempLabel(NULL);
8593       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8594                 pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8595                 pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8596       }
8597
8598       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8599       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8600       pic16_emitpLabel(tlbl->key);
8601       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8602       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8603       emitSKPC;
8604       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8605     }
8606     goto release ;
8607   }
8608     
8609   if (pic16_sameRegs(AOP(left),AOP(result))) {
8610
8611     tlbl = newiTempLabel(NULL);
8612     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8613     genMultiAsm(POC_RRCF, result, size,1);
8614     pic16_emitpLabel(tlbl->key);
8615     genMultiAsm(POC_RLCF, result, size,0);
8616     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8617     emitSKPC;
8618     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8619     goto release;
8620   }
8621
8622   //tlbl = newiTempLabel(NULL);
8623   //offset = 0 ;   
8624   //tlbl1 = newiTempLabel(NULL);
8625
8626   //reAdjustPreg(AOP(result));    
8627     
8628   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
8629   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8630   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8631   //MOVA(l);
8632   //pic16_emitcode("add","a,acc");         
8633   //pic16_aopPut(AOP(result),"a",offset++);
8634   //while (--size) {
8635   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8636   //  MOVA(l);
8637   //  pic16_emitcode("rlc","a");         
8638   //  pic16_aopPut(AOP(result),"a",offset++);
8639   //}
8640   //reAdjustPreg(AOP(result));
8641
8642   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8643   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8644
8645
8646   tlbl = newiTempLabel(NULL);
8647   tlbl1= newiTempLabel(NULL);
8648
8649   size = AOP_SIZE(result);
8650   offset = 1;
8651
8652   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8653
8654   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8655
8656   /* offset should be 0, 1 or 3 */
8657   
8658   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8659   emitSKPNZ;
8660   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8661
8662   pic16_emitpcode(POC_MOVWF, pctemp);
8663
8664
8665   pic16_emitpLabel(tlbl->key);
8666
8667   emitCLRC;
8668   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
8669   while(--size)
8670     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
8671
8672   pic16_emitpcode(POC_DECFSZ,  pctemp);
8673   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8674   pic16_emitpLabel(tlbl1->key);
8675
8676   pic16_popReleaseTempReg(pctemp);
8677
8678
8679  release:
8680   pic16_freeAsmop (right,NULL,ic,TRUE);
8681   pic16_freeAsmop(left,NULL,ic,TRUE);
8682   pic16_freeAsmop(result,NULL,ic,TRUE);
8683 }
8684
8685 /*-----------------------------------------------------------------*/
8686 /* genrshOne - right shift a one byte quantity by known count      */
8687 /*-----------------------------------------------------------------*/
8688 static void genrshOne (operand *result, operand *left,
8689                        int shCount, int sign)
8690 {
8691     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8692     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8693 }
8694
8695 /*-----------------------------------------------------------------*/
8696 /* genrshTwo - right shift two bytes by known amount != 0          */
8697 /*-----------------------------------------------------------------*/
8698 static void genrshTwo (operand *result,operand *left,
8699                        int shCount, int sign)
8700 {
8701   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8702   /* if shCount >= 8 */
8703   if (shCount >= 8) {
8704     shCount -= 8 ;
8705     if (shCount)
8706       shiftR1Left2Result(left, MSB16, result, LSB,
8707                          shCount, sign);
8708     else
8709       movLeft2Result(left, MSB16, result, LSB);
8710
8711     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8712
8713     if(sign) {
8714       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8715       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8716     }
8717   }
8718
8719   /*  1 <= shCount <= 7 */
8720   else
8721     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
8722 }
8723
8724 /*-----------------------------------------------------------------*/
8725 /* shiftRLong - shift right one long from left to result           */
8726 /* offl = LSB or MSB16                                             */
8727 /*-----------------------------------------------------------------*/
8728 static void shiftRLong (operand *left, int offl,
8729                         operand *result, int sign)
8730 {
8731     int size = AOP_SIZE(result);
8732     int same = pic16_sameRegs(AOP(left),AOP(result));
8733     int i;
8734     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8735
8736         if (same && (offl == MSB16)) { //shift one byte right
8737                 for(i=MSB16;i<size;i++) {
8738                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8739                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8740                 }
8741         }
8742
8743     if(sign)
8744                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8745         else
8746                 emitCLRC;
8747
8748         if (same) {
8749                 if (offl == LSB)
8750                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8751         } else {
8752         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8753         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8754         }
8755
8756     if(offl == MSB16) {
8757         /* add sign of "a" */
8758         pic16_addSign(result, MSB32, sign);
8759         }
8760
8761         if (same) {
8762         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8763         } else {
8764         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8765         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8766         }
8767         
8768         if (same) {
8769         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8770         } else {
8771         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8772         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8773         }
8774
8775         if (same) {
8776         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8777         } else {
8778         if(offl == LSB){
8779                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8780                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8781         }
8782         }
8783 }
8784
8785 /*-----------------------------------------------------------------*/
8786 /* genrshFour - shift four byte by a known amount != 0             */
8787 /*-----------------------------------------------------------------*/
8788 static void genrshFour (operand *result, operand *left,
8789                         int shCount, int sign)
8790 {
8791   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8792   /* if shifting more that 3 bytes */
8793   if(shCount >= 24 ) {
8794     shCount -= 24;
8795     if(shCount)
8796       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8797     else
8798       movLeft2Result(left, MSB32, result, LSB);
8799
8800     pic16_addSign(result, MSB16, sign);
8801   }
8802   else if(shCount >= 16){
8803     shCount -= 16;
8804     if(shCount)
8805       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8806     else{
8807       movLeft2Result(left, MSB24, result, LSB);
8808       movLeft2Result(left, MSB32, result, MSB16);
8809     }
8810     pic16_addSign(result, MSB24, sign);
8811   }
8812   else if(shCount >= 8){
8813     shCount -= 8;
8814     if(shCount == 1)
8815       shiftRLong(left, MSB16, result, sign);
8816     else if(shCount == 0){
8817       movLeft2Result(left, MSB16, result, LSB);
8818       movLeft2Result(left, MSB24, result, MSB16);
8819       movLeft2Result(left, MSB32, result, MSB24);
8820       pic16_addSign(result, MSB32, sign);
8821     }
8822     else{ //shcount >= 2
8823       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8824       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8825       /* the last shift is signed */
8826       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8827       pic16_addSign(result, MSB32, sign);
8828     }
8829   }
8830   else{   /* 1 <= shCount <= 7 */
8831     if(shCount <= 2){
8832       shiftRLong(left, LSB, result, sign);
8833       if(shCount == 2)
8834         shiftRLong(result, LSB, result, sign);
8835     }
8836     else{
8837       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8838       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8839       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8840     }
8841   }
8842 }
8843
8844 /*-----------------------------------------------------------------*/
8845 /* genRightShiftLiteral - right shifting by known count            */
8846 /*-----------------------------------------------------------------*/
8847 static void genRightShiftLiteral (operand *left,
8848                                   operand *right,
8849                                   operand *result,
8850                                   iCode *ic,
8851                                   int sign)
8852 {    
8853   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8854   int lsize,res_size;
8855
8856   pic16_freeAsmop(right,NULL,ic,TRUE);
8857
8858   pic16_aopOp(left,ic,FALSE);
8859   pic16_aopOp(result,ic,FALSE);
8860
8861   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8862
8863 #if VIEW_SIZE
8864   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8865                  AOP_SIZE(left));
8866 #endif
8867
8868   lsize = pic16_getDataSize(left);
8869   res_size = pic16_getDataSize(result);
8870   /* test the LEFT size !!! */
8871
8872   /* I suppose that the left size >= result size */
8873   if(shCount == 0){
8874     while(res_size--)
8875       movLeft2Result(left, lsize, result, res_size);
8876   }
8877
8878   else if(shCount >= (lsize * 8)){
8879
8880     if(res_size == 1) {
8881       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8882       if(sign) {
8883         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8884         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8885       }
8886     } else {
8887
8888       if(sign) {
8889         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8890         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8891         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8892         while(res_size--)
8893           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8894
8895       } else {
8896
8897         while(res_size--)
8898           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8899       }
8900     }
8901   } else {
8902
8903     switch (res_size) {
8904     case 1:
8905       genrshOne (result,left,shCount,sign);
8906       break;
8907
8908     case 2:
8909       genrshTwo (result,left,shCount,sign);
8910       break;
8911
8912     case 4:
8913       genrshFour (result,left,shCount,sign);
8914       break;
8915     default :
8916       break;
8917     }
8918
8919   }
8920
8921   pic16_freeAsmop(left,NULL,ic,TRUE);
8922   pic16_freeAsmop(result,NULL,ic,TRUE);
8923 }
8924
8925 /*-----------------------------------------------------------------*/
8926 /* genSignedRightShift - right shift of signed number              */
8927 /*-----------------------------------------------------------------*/
8928 static void genSignedRightShift (iCode *ic)
8929 {
8930   operand *right, *left, *result;
8931   int size, offset;
8932   //  char *l;
8933   symbol *tlbl, *tlbl1 ;
8934   pCodeOp *pctemp;
8935
8936   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8937
8938   /* we do it the hard way put the shift count in b
8939      and loop thru preserving the sign */
8940   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8941
8942   right = IC_RIGHT(ic);
8943   left  = IC_LEFT(ic);
8944   result = IC_RESULT(ic);
8945
8946   pic16_aopOp(right,ic,FALSE);  
8947   pic16_aopOp(left,ic,FALSE);
8948   pic16_aopOp(result,ic,FALSE);
8949
8950
8951   if ( AOP_TYPE(right) == AOP_LIT) {
8952     genRightShiftLiteral (left,right,result,ic,1);
8953     return ;
8954   }
8955   /* shift count is unknown then we have to form 
8956      a loop get the loop count in B : Note: we take
8957      only the lower order byte since shifting
8958      more that 32 bits make no sense anyway, ( the
8959      largest size of an object can be only 32 bits ) */  
8960
8961   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8962   //pic16_emitcode("inc","b");
8963   //pic16_freeAsmop (right,NULL,ic,TRUE);
8964   //pic16_aopOp(left,ic,FALSE);
8965   //pic16_aopOp(result,ic,FALSE);
8966
8967   /* now move the left to the result if they are not the
8968      same */
8969   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8970       AOP_SIZE(result) > 1) {
8971
8972     size = AOP_SIZE(result);
8973     offset=0;
8974     while (size--) { 
8975       /*
8976         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8977         if (*l == '@' && IS_AOP_PREG(result)) {
8978
8979         pic16_emitcode("mov","a,%s",l);
8980         pic16_aopPut(AOP(result),"a",offset);
8981         } else
8982         pic16_aopPut(AOP(result),l,offset);
8983       */
8984       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8985       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8986
8987       offset++;
8988     }
8989   }
8990
8991   /* mov the highest order bit to OVR */    
8992   tlbl = newiTempLabel(NULL);
8993   tlbl1= newiTempLabel(NULL);
8994
8995   size = AOP_SIZE(result);
8996   offset = size - 1;
8997
8998   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8999
9000   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9001
9002   /* offset should be 0, 1 or 3 */
9003   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
9004   emitSKPNZ;
9005   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9006
9007   pic16_emitpcode(POC_MOVWF, pctemp);
9008
9009
9010   pic16_emitpLabel(tlbl->key);
9011
9012   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
9013   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
9014
9015   while(--size) {
9016     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
9017   }
9018
9019   pic16_emitpcode(POC_DECFSZ,  pctemp);
9020   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9021   pic16_emitpLabel(tlbl1->key);
9022
9023   pic16_popReleaseTempReg(pctemp);
9024 #if 0
9025   size = AOP_SIZE(result);
9026   offset = size - 1;
9027   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
9028   pic16_emitcode("rlc","a");
9029   pic16_emitcode("mov","ov,c");
9030   /* if it is only one byte then */
9031   if (size == 1) {
9032     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9033     MOVA(l);
9034     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9035     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9036     pic16_emitcode("mov","c,ov");
9037     pic16_emitcode("rrc","a");
9038     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9039     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9040     pic16_aopPut(AOP(result),"a",0);
9041     goto release ;
9042   }
9043
9044   reAdjustPreg(AOP(result));
9045   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9046   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9047   pic16_emitcode("mov","c,ov");
9048   while (size--) {
9049     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9050     MOVA(l);
9051     pic16_emitcode("rrc","a");         
9052     pic16_aopPut(AOP(result),"a",offset--);
9053   }
9054   reAdjustPreg(AOP(result));
9055   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9056   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9057
9058  release:
9059 #endif
9060
9061   pic16_freeAsmop(left,NULL,ic,TRUE);
9062   pic16_freeAsmop(result,NULL,ic,TRUE);
9063   pic16_freeAsmop(right,NULL,ic,TRUE);
9064 }
9065
9066 /*-----------------------------------------------------------------*/
9067 /* genRightShift - generate code for right shifting                */
9068 /*-----------------------------------------------------------------*/
9069 static void genRightShift (iCode *ic)
9070 {
9071     operand *right, *left, *result;
9072     sym_link *letype ;
9073     int size, offset;
9074     char *l;
9075     symbol *tlbl, *tlbl1 ;
9076
9077     /* if signed then we do it the hard way preserve the
9078     sign bit moving it inwards */
9079     letype = getSpec(operandType(IC_LEFT(ic)));
9080     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9081
9082     if (!SPEC_USIGN(letype)) {
9083         genSignedRightShift (ic);
9084         return ;
9085     }
9086
9087     /* signed & unsigned types are treated the same : i.e. the
9088     signed is NOT propagated inwards : quoting from the
9089     ANSI - standard : "for E1 >> E2, is equivalent to division
9090     by 2**E2 if unsigned or if it has a non-negative value,
9091     otherwise the result is implementation defined ", MY definition
9092     is that the sign does not get propagated */
9093
9094     right = IC_RIGHT(ic);
9095     left  = IC_LEFT(ic);
9096     result = IC_RESULT(ic);
9097
9098     pic16_aopOp(right,ic,FALSE);
9099
9100     /* if the shift count is known then do it 
9101     as efficiently as possible */
9102     if (AOP_TYPE(right) == AOP_LIT) {
9103         genRightShiftLiteral (left,right,result,ic, 0);
9104         return ;
9105     }
9106
9107     /* shift count is unknown then we have to form 
9108     a loop get the loop count in B : Note: we take
9109     only the lower order byte since shifting
9110     more that 32 bits make no sense anyway, ( the
9111     largest size of an object can be only 32 bits ) */  
9112
9113     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9114     pic16_emitcode("inc","b");
9115     pic16_aopOp(left,ic,FALSE);
9116     pic16_aopOp(result,ic,FALSE);
9117
9118     /* now move the left to the result if they are not the
9119     same */
9120     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9121         AOP_SIZE(result) > 1) {
9122
9123         size = AOP_SIZE(result);
9124         offset=0;
9125         while (size--) {
9126             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9127             if (*l == '@' && IS_AOP_PREG(result)) {
9128
9129                 pic16_emitcode("mov","a,%s",l);
9130                 pic16_aopPut(AOP(result),"a",offset);
9131             } else
9132                 pic16_aopPut(AOP(result),l,offset);
9133             offset++;
9134         }
9135     }
9136
9137     tlbl = newiTempLabel(NULL);
9138     tlbl1= newiTempLabel(NULL);
9139     size = AOP_SIZE(result);
9140     offset = size - 1;
9141
9142     /* if it is only one byte then */
9143     if (size == 1) {
9144
9145       tlbl = newiTempLabel(NULL);
9146       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9147         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9148         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9149       }
9150
9151       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9152       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9153       pic16_emitpLabel(tlbl->key);
9154       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9155       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9156       emitSKPC;
9157       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9158
9159       goto release ;
9160     }
9161
9162     reAdjustPreg(AOP(result));
9163     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9164     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9165     CLRC;
9166     while (size--) {
9167         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9168         MOVA(l);
9169         pic16_emitcode("rrc","a");         
9170         pic16_aopPut(AOP(result),"a",offset--);
9171     }
9172     reAdjustPreg(AOP(result));
9173
9174     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9175     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9176
9177 release:
9178     pic16_freeAsmop(left,NULL,ic,TRUE);
9179     pic16_freeAsmop (right,NULL,ic,TRUE);
9180     pic16_freeAsmop(result,NULL,ic,TRUE);
9181 }
9182
9183 /*-----------------------------------------------------------------*/
9184 /* genUnpackBits - generates code for unpacking bits               */
9185 /*-----------------------------------------------------------------*/
9186 static void genUnpackBits (operand *result, char *rname, int ptype)
9187 {    
9188     int shCnt ;
9189     int rlen = 0 ;
9190     sym_link *etype;
9191     int offset = 0 ;
9192
9193         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9194         etype = getSpec(operandType(result));
9195
9196         /* read the first byte  */
9197         switch (ptype) {
9198                 case POINTER:
9199                 case IPOINTER:
9200                 case PPOINTER:
9201                 case FPOINTER:
9202                 case GPOINTER:
9203                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9204                         break;
9205                 case CPOINTER:
9206                         pic16_emitcode("clr","a");
9207                         pic16_emitcode("movc","a","@a+dptr");
9208                         break;
9209         }
9210         
9211
9212         /* if we have bitdisplacement then it fits   */
9213         /* into this byte completely or if length is */
9214         /* less than a byte                          */
9215         if ((shCnt = SPEC_BSTR(etype)) || 
9216                 (SPEC_BLEN(etype) <= 8))  {
9217
9218                 /* shift right acc */
9219                 AccRsh(shCnt, 0);
9220
9221                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9222                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9223
9224 /* VR -- normally I would use the following, but since we use the hack,
9225  * to avoid the masking from AccRsh, why not mask it right now? */
9226
9227 /*
9228                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9229 */
9230
9231                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9232           return ;
9233         }
9234
9235
9236
9237         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9238         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9239         exit(-1);
9240
9241     /* bit field did not fit in a byte  */
9242     rlen = SPEC_BLEN(etype) - 8;
9243     pic16_aopPut(AOP(result),"a",offset++);
9244
9245     while (1)  {
9246
9247         switch (ptype) {
9248         case POINTER:
9249         case IPOINTER:
9250             pic16_emitcode("inc","%s",rname);
9251             pic16_emitcode("mov","a,@%s",rname);
9252             break;
9253             
9254         case PPOINTER:
9255             pic16_emitcode("inc","%s",rname);
9256             pic16_emitcode("movx","a,@%s",rname);
9257             break;
9258
9259         case FPOINTER:
9260             pic16_emitcode("inc","dptr");
9261             pic16_emitcode("movx","a,@dptr");
9262             break;
9263             
9264         case CPOINTER:
9265             pic16_emitcode("clr","a");
9266             pic16_emitcode("inc","dptr");
9267             pic16_emitcode("movc","a","@a+dptr");
9268             break;
9269             
9270         case GPOINTER:
9271             pic16_emitcode("inc","dptr");
9272             pic16_emitcode("lcall","__gptrget");
9273             break;
9274         }
9275
9276         rlen -= 8;            
9277         /* if we are done */
9278         if ( rlen <= 0 )
9279             break ;
9280         
9281         pic16_aopPut(AOP(result),"a",offset++);
9282                               
9283     }
9284     
9285     if (rlen) {
9286         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9287         pic16_aopPut(AOP(result),"a",offset);          
9288     }
9289     
9290     return ;
9291 }
9292
9293
9294 static void genDataPointerGet(operand *left,
9295                               operand *result,
9296                               iCode *ic)
9297 {
9298   int size, offset = 0, leoffset=0 ;
9299
9300         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9301         pic16_aopOp(result, ic, FALSE);
9302
9303         size = AOP_SIZE(result);
9304 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9305
9306
9307 #if 0
9308         /* The following tests may save a redudant movff instruction when
9309          * accessing unions */
9310          
9311         /* if they are the same */
9312         if (operandsEqu (left, result)) {
9313                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9314                 goto release;
9315         }
9316 #endif
9317
9318 #if 0
9319         /* if they are the same registers */
9320         if (pic16_sameRegs(AOP(left),AOP(result))) {
9321                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9322                 goto release;
9323         }
9324 #endif
9325
9326 #if 1
9327         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9328                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9329                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9330                 goto release;
9331         }
9332 #endif
9333
9334
9335 #if 0
9336         if ( AOP_TYPE(left) == AOP_PCODE) {
9337                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
9338                                 AOP(left)->aopu.pcop->name,
9339                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
9340                                 PCOR(AOP(left)->aopu.pcop)->instance:
9341                                 PCOI(AOP(left)->aopu.pcop)->offset);
9342         }
9343 #endif
9344
9345         if(AOP(left)->aopu.pcop->type == PO_DIR)
9346                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9347
9348         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9349
9350         while (size--) {
9351                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9352                 
9353                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9354                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9355                         mov2w(AOP(left), offset); // patch 8
9356                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9357                 } else {
9358                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9359                                 pic16_popGet(AOP(left), offset), //patch 8
9360                                 pic16_popGet(AOP(result), offset)));
9361                 }
9362
9363                 offset++;
9364                 leoffset++;
9365         }
9366
9367 release:
9368     pic16_freeAsmop(result,NULL,ic,TRUE);
9369 }
9370
9371 void pic16_loadFSR0(operand *op)
9372 {
9373         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9374 }
9375
9376
9377 /*-----------------------------------------------------------------*/
9378 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
9379 /*-----------------------------------------------------------------*/
9380 static void genNearPointerGet (operand *left, 
9381                                operand *result, 
9382                                iCode *ic)
9383 {
9384     asmop *aop = NULL;
9385     //regs *preg = NULL ;
9386     sym_link *rtype, *retype;
9387     sym_link *ltype = operandType(left);    
9388
9389         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9390         rtype = operandType(result);
9391         retype= getSpec(rtype);
9392     
9393         pic16_aopOp(left,ic,FALSE);
9394
9395 //      pic16_DumpOp("(left)",left);
9396 //      pic16_DumpOp("(result)",result);
9397
9398         /* if left is rematerialisable and
9399          * result is not bit variable type and
9400          * the left is pointer to data space i.e
9401          * lower 128 bytes of space */
9402         if (AOP_TYPE(left) == AOP_PCODE
9403                 && !IS_BITFIELD(retype)
9404                 && DCL_TYPE(ltype) == POINTER) {
9405
9406                 genDataPointerGet (left,result,ic);
9407                 pic16_freeAsmop(left, NULL, ic, TRUE);
9408           return ;
9409         }
9410     
9411         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9412
9413         /* if the value is already in a pointer register
9414          * then don't need anything more */
9415         if (!AOP_INPREG(AOP(left))) {
9416                 /* otherwise get a free pointer register */
9417                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9418                 
9419                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9420                 if( (AOP_TYPE(left) == AOP_PCODE) 
9421                         && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9422                                 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9423                 {
9424                         pic16_loadFSR0( left );  // patch 10
9425                 } else {
9426                         // set up FSR0 with address from left
9427                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9428                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9429                 }
9430         }
9431 //       else
9432 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9433     
9434         pic16_aopOp (result,ic,FALSE);
9435     
9436       /* if bitfield then unpack the bits */
9437     if (IS_BITFIELD(retype)) 
9438         genUnpackBits (result, NULL, POINTER);
9439     else {
9440         /* we have can just get the values */
9441       int size = AOP_SIZE(result);
9442       int offset = 0;   
9443         
9444       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9445
9446
9447         /* fsr0 is loaded already -- VR */
9448 //      pic16_loadFSR0( left );
9449
9450 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9451 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9452       while(size--) {
9453
9454         if(size) {
9455                 pic16_emitpcode(POC_MOVFF,
9456                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9457                                 pic16_popGet(AOP(result), offset++)));
9458         } else {
9459                 pic16_emitpcode(POC_MOVFF,
9460                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9461                                 pic16_popGet(AOP(result), offset++)));
9462         }
9463       }
9464 #if 0
9465 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9466 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9467         if(size)
9468           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9469 #endif
9470 /*
9471         while (size--) {
9472             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9473
9474                 pic16_emitcode("mov","a,@%s",rname);
9475                 pic16_aopPut(AOP(result),"a",offset);
9476             } else {
9477                 sprintf(buffer,"@%s",rname);
9478                 pic16_aopPut(AOP(result),buffer,offset);
9479             }
9480             offset++ ;
9481             if (size)
9482                 pic16_emitcode("inc","%s",rname);
9483         }
9484 */
9485     }
9486
9487     /* now some housekeeping stuff */
9488     if (aop) {
9489         /* we had to allocate for this iCode */
9490     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9491         pic16_freeAsmop(NULL,aop,ic,TRUE);
9492     } else { 
9493         /* we did not allocate which means left
9494            already in a pointer register, then
9495            if size > 0 && this could be used again
9496            we have to point it back to where it 
9497            belongs */
9498     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9499         if (AOP_SIZE(result) > 1 &&
9500             !OP_SYMBOL(left)->remat &&
9501             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9502               ic->depth )) {
9503 //          int size = AOP_SIZE(result) - 1;
9504 //          while (size--)
9505 //              pic16_emitcode("dec","%s",rname);
9506         }
9507     }
9508
9509     /* done */
9510     pic16_freeAsmop(left,NULL,ic,TRUE);
9511     pic16_freeAsmop(result,NULL,ic,TRUE);
9512      
9513 }
9514
9515 /*-----------------------------------------------------------------*/
9516 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
9517 /*-----------------------------------------------------------------*/
9518 static void genPagedPointerGet (operand *left, 
9519                                operand *result, 
9520                                iCode *ic)
9521 {
9522     asmop *aop = NULL;
9523     regs *preg = NULL ;
9524     char *rname ;
9525     sym_link *rtype, *retype;    
9526
9527     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9528
9529     rtype = operandType(result);
9530     retype= getSpec(rtype);
9531     
9532     pic16_aopOp(left,ic,FALSE);
9533
9534   /* if the value is already in a pointer register
9535        then don't need anything more */
9536     if (!AOP_INPREG(AOP(left))) {
9537         /* otherwise get a free pointer register */
9538         aop = newAsmop(0);
9539         preg = getFreePtr(ic,&aop,FALSE);
9540         pic16_emitcode("mov","%s,%s",
9541                 preg->name,
9542                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9543         rname = preg->name ;
9544     } else
9545         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9546     
9547     pic16_freeAsmop(left,NULL,ic,TRUE);
9548     pic16_aopOp (result,ic,FALSE);
9549
9550     /* if bitfield then unpack the bits */
9551     if (IS_BITFIELD(retype)) 
9552         genUnpackBits (result,rname,PPOINTER);
9553     else {
9554         /* we have can just get the values */
9555         int size = AOP_SIZE(result);
9556         int offset = 0 ;        
9557         
9558         while (size--) {
9559             
9560             pic16_emitcode("movx","a,@%s",rname);
9561             pic16_aopPut(AOP(result),"a",offset);
9562             
9563             offset++ ;
9564             
9565             if (size)
9566                 pic16_emitcode("inc","%s",rname);
9567         }
9568     }
9569
9570     /* now some housekeeping stuff */
9571     if (aop) {
9572         /* we had to allocate for this iCode */
9573         pic16_freeAsmop(NULL,aop,ic,TRUE);
9574     } else { 
9575         /* we did not allocate which means left
9576            already in a pointer register, then
9577            if size > 0 && this could be used again
9578            we have to point it back to where it 
9579            belongs */
9580         if (AOP_SIZE(result) > 1 &&
9581             !OP_SYMBOL(left)->remat &&
9582             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9583               ic->depth )) {
9584             int size = AOP_SIZE(result) - 1;
9585             while (size--)
9586                 pic16_emitcode("dec","%s",rname);
9587         }
9588     }
9589
9590     /* done */
9591     pic16_freeAsmop(result,NULL,ic,TRUE);
9592     
9593         
9594 }
9595
9596 /*-----------------------------------------------------------------*/
9597 /* genFarPointerGet - gget value from far space                    */
9598 /*-----------------------------------------------------------------*/
9599 static void genFarPointerGet (operand *left,
9600                               operand *result, iCode *ic)
9601 {
9602     int size, offset ;
9603     sym_link *retype = getSpec(operandType(result));
9604
9605     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9606
9607     pic16_aopOp(left,ic,FALSE);
9608
9609     /* if the operand is already in dptr 
9610     then we do nothing else we move the value to dptr */
9611     if (AOP_TYPE(left) != AOP_STR) {
9612         /* if this is remateriazable */
9613         if (AOP_TYPE(left) == AOP_IMMD)
9614             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9615         else { /* we need to get it byte by byte */
9616             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9617             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9618             if (options.model == MODEL_FLAT24)
9619             {
9620                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9621             }
9622         }
9623     }
9624     /* so dptr know contains the address */
9625     pic16_freeAsmop(left,NULL,ic,TRUE);
9626     pic16_aopOp(result,ic,FALSE);
9627
9628     /* if bit then unpack */
9629     if (IS_BITFIELD(retype)) 
9630         genUnpackBits(result,"dptr",FPOINTER);
9631     else {
9632         size = AOP_SIZE(result);
9633         offset = 0 ;
9634
9635         while (size--) {
9636             pic16_emitcode("movx","a,@dptr");
9637             pic16_aopPut(AOP(result),"a",offset++);
9638             if (size)
9639                 pic16_emitcode("inc","dptr");
9640         }
9641     }
9642
9643     pic16_freeAsmop(result,NULL,ic,TRUE);
9644 }
9645 #if 0
9646 /*-----------------------------------------------------------------*/
9647 /* genCodePointerGet - get value from code space                  */
9648 /*-----------------------------------------------------------------*/
9649 static void genCodePointerGet (operand *left,
9650                                 operand *result, iCode *ic)
9651 {
9652     int size, offset ;
9653     sym_link *retype = getSpec(operandType(result));
9654
9655     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9656
9657     pic16_aopOp(left,ic,FALSE);
9658
9659     /* if the operand is already in dptr 
9660     then we do nothing else we move the value to dptr */
9661     if (AOP_TYPE(left) != AOP_STR) {
9662         /* if this is remateriazable */
9663         if (AOP_TYPE(left) == AOP_IMMD)
9664             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9665         else { /* we need to get it byte by byte */
9666             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9667             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9668             if (options.model == MODEL_FLAT24)
9669             {
9670                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9671             }
9672         }
9673     }
9674     /* so dptr know contains the address */
9675     pic16_freeAsmop(left,NULL,ic,TRUE);
9676     pic16_aopOp(result,ic,FALSE);
9677
9678     /* if bit then unpack */
9679     if (IS_BITFIELD(retype)) 
9680         genUnpackBits(result,"dptr",CPOINTER);
9681     else {
9682         size = AOP_SIZE(result);
9683         offset = 0 ;
9684
9685         while (size--) {
9686             pic16_emitcode("clr","a");
9687             pic16_emitcode("movc","a,@a+dptr");
9688             pic16_aopPut(AOP(result),"a",offset++);
9689             if (size)
9690                 pic16_emitcode("inc","dptr");
9691         }
9692     }
9693
9694     pic16_freeAsmop(result,NULL,ic,TRUE);
9695 }
9696 #endif
9697 /*-----------------------------------------------------------------*/
9698 /* genGenPointerGet - gget value from generic pointer space        */
9699 /*-----------------------------------------------------------------*/
9700 static void genGenPointerGet (operand *left,
9701                               operand *result, iCode *ic)
9702 {
9703   int size, offset, lit;
9704   sym_link *retype = getSpec(operandType(result));
9705
9706         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9707         pic16_aopOp(left,ic,FALSE);
9708         pic16_aopOp(result,ic,FALSE);
9709         size = AOP_SIZE(result);
9710
9711         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9712
9713         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9714
9715                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9716                 // load FSR0 from immediate
9717                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9718
9719 //              pic16_loadFSR0( left );
9720
9721                 offset = 0;
9722                 while(size--) {
9723                         if(size) {
9724                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9725                         } else {
9726                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9727                         }
9728                         offset++;
9729                 }
9730                 goto release;
9731
9732         }
9733         else { /* we need to get it byte by byte */
9734                 // set up FSR0 with address from left
9735                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9736                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9737
9738                 offset = 0 ;
9739
9740                 while(size--) {
9741                         if(size) {
9742                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9743                         } else {
9744                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9745                         }
9746                         offset++;
9747                 }
9748                 goto release;
9749         }
9750
9751   /* if bit then unpack */
9752         if (IS_BITFIELD(retype)) 
9753                 genUnpackBits(result,"BAD",GPOINTER);
9754
9755         release:
9756         pic16_freeAsmop(left,NULL,ic,TRUE);
9757         pic16_freeAsmop(result,NULL,ic,TRUE);
9758
9759 }
9760
9761 /*-----------------------------------------------------------------*/
9762 /* genConstPointerGet - get value from const generic pointer space */
9763 /*-----------------------------------------------------------------*/
9764 static void genConstPointerGet (operand *left,
9765                                 operand *result, iCode *ic)
9766 {
9767   //sym_link *retype = getSpec(operandType(result));
9768   // symbol *albl = newiTempLabel(NULL);        // patch 15
9769   // symbol *blbl = newiTempLabel(NULL);        //
9770   // PIC_OPCODE poc;                            // patch 15
9771   int size;
9772   int offset = 0;
9773
9774   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9775   pic16_aopOp(left,ic,FALSE);
9776   pic16_aopOp(result,ic,TRUE);
9777   size = AOP_SIZE(result);
9778
9779   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9780
9781   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9782 #if 0                                                                   // patch 15
9783   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9784   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9785   pic16_emitpLabel(albl->key);
9786
9787   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9788     
9789   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9790   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9791   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9792   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9793   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9794
9795   pic16_emitpLabel(blbl->key);
9796
9797   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9798 #endif                                                                  // patch 15
9799
9800
9801   // set up table pointer
9802   if( (AOP_TYPE(left) == AOP_PCODE) 
9803       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9804           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
9805     {
9806       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9807       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9808       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9809       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9810       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9811       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9812     }
9813   else
9814     {
9815       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9816       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9817       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9818     }
9819
9820
9821   while(size--)
9822     {
9823       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9824       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9825       offset++;
9826     }
9827     
9828   pic16_freeAsmop(left,NULL,ic,TRUE);
9829   pic16_freeAsmop(result,NULL,ic,TRUE);
9830
9831 }
9832
9833
9834 /*-----------------------------------------------------------------*/
9835 /* genPointerGet - generate code for pointer get                   */
9836 /*-----------------------------------------------------------------*/
9837 static void genPointerGet (iCode *ic)
9838 {
9839     operand *left, *result ;
9840     sym_link *type, *etype;
9841     int p_type;
9842
9843     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9844
9845     left = IC_LEFT(ic);
9846     result = IC_RESULT(ic) ;
9847
9848     /* depending on the type of pointer we need to
9849     move it to the correct pointer register */
9850     type = operandType(left);
9851     etype = getSpec(type);
9852
9853 #if 0
9854     if (IS_PTR_CONST(type))
9855 #else
9856     if (IS_CODEPTR(type))
9857 #endif
9858       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9859
9860     /* if left is of type of pointer then it is simple */
9861     if (IS_PTR(type) && !IS_FUNC(type->next)) 
9862         p_type = DCL_TYPE(type);
9863     else {
9864         /* we have to go by the storage class */
9865         p_type = PTR_TYPE(SPEC_OCLS(etype));
9866
9867         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9868
9869         if (SPEC_OCLS(etype)->codesp ) {
9870           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9871           //p_type = CPOINTER ; 
9872         }
9873         else
9874             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9875               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9876                /*p_type = FPOINTER ;*/ 
9877             else
9878                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9879                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9880 /*                  p_type = PPOINTER; */
9881                 else
9882                     if (SPEC_OCLS(etype) == idata )
9883                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9884 /*                      p_type = IPOINTER; */
9885                     else
9886                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9887 /*                      p_type = POINTER ; */
9888     }
9889
9890     /* now that we have the pointer type we assign
9891     the pointer values */
9892     switch (p_type) {
9893
9894     case POINTER:       
9895     case IPOINTER:
9896         genNearPointerGet (left,result,ic);
9897         break;
9898
9899     case PPOINTER:
9900         genPagedPointerGet(left,result,ic);
9901         break;
9902
9903     case FPOINTER:
9904         genFarPointerGet (left,result,ic);
9905         break;
9906
9907     case CPOINTER:
9908         genConstPointerGet (left,result,ic);
9909         //pic16_emitcodePointerGet (left,result,ic);
9910         break;
9911
9912     case GPOINTER:
9913 #if 0
9914       if (IS_PTR_CONST(type))
9915         genConstPointerGet (left,result,ic);
9916       else
9917 #endif
9918         genGenPointerGet (left,result,ic);
9919       break;
9920
9921     default:
9922       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9923               "genPointerGet: illegal pointer type");
9924     
9925     }
9926
9927 }
9928
9929 /*-----------------------------------------------------------------*/
9930 /* genPackBits - generates code for packed bit storage             */
9931 /*-----------------------------------------------------------------*/
9932 static void genPackBits (sym_link    *etype ,
9933                          operand *right ,
9934                          char *rname, int p_type)
9935 {
9936   int shCnt = 0 ;
9937   int offset = 0  ;
9938   int rLen = 0 ;
9939   int blen, bstr ;   
9940   char *l ;
9941
9942         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9943         blen = SPEC_BLEN(etype);
9944         bstr = SPEC_BSTR(etype);
9945
9946         if(AOP_TYPE(right) == AOP_LIT) {
9947                 if((blen == 1) && (bstr < 8)) {
9948                   unsigned long lit;
9949                         /* it is a single bit, so use the appropriate bit instructions */
9950
9951                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
9952
9953                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9954 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9955                         if(lit) {
9956                                 pic16_emitpcode(POC_BSF,
9957                                         pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9958                         } else {
9959                                 pic16_emitpcode(POC_BCF,
9960                                         pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9961                         }
9962         
9963                   return;
9964                 }
9965
9966                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9967                 offset++;
9968         } else
9969                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9970
9971         /* if the bit lenth is less than or    */
9972         /* it exactly fits a byte then         */
9973         if((shCnt=SPEC_BSTR(etype))
9974                 || SPEC_BLEN(etype) <= 8 )  {
9975
9976                 /* shift left acc */
9977                 AccLsh(shCnt);
9978
9979                 /* using PRODL as a temporary register here */
9980                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9981
9982                 switch (p_type) {
9983                         case FPOINTER:
9984                         case POINTER:
9985                         case GPOINTER:
9986                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9987 //                              pic16_emitcode ("mov","b,a");
9988 //                              pic16_emitcode("mov","a,@%s",rname);
9989                                 break;
9990                 }
9991 #if 1
9992                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9993                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9994                                         (unsigned char)(0xff >> (8-bstr))) ));
9995                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9996                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9997 #endif
9998
9999           return;
10000         }
10001
10002
10003         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10004         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10005         exit(-1);
10006
10007
10008     /* if we r done */
10009     if ( SPEC_BLEN(etype) <= 8 )
10010         return ;
10011
10012     pic16_emitcode("inc","%s",rname);
10013     rLen = SPEC_BLEN(etype) ;     
10014
10015
10016
10017     /* now generate for lengths greater than one byte */
10018     while (1) {
10019
10020         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
10021
10022         rLen -= 8 ;
10023         if (rLen <= 0 )
10024             break ;
10025
10026         switch (p_type) {
10027             case POINTER:
10028                 if (*l == '@') {
10029                     MOVA(l);
10030                     pic16_emitcode("mov","@%s,a",rname);
10031                 } else
10032                     pic16_emitcode("mov","@%s,%s",rname,l);
10033                 break;
10034
10035             case FPOINTER:
10036                 MOVA(l);
10037                 pic16_emitcode("movx","@dptr,a");
10038                 break;
10039
10040             case GPOINTER:
10041                 MOVA(l);
10042                 DEBUGpic16_emitcode(";lcall","__gptrput");
10043                 break;  
10044         }   
10045         pic16_emitcode ("inc","%s",rname);
10046     }
10047
10048     MOVA(l);
10049
10050     /* last last was not complete */
10051     if (rLen)   {
10052         /* save the byte & read byte */
10053         switch (p_type) {
10054             case POINTER:
10055                 pic16_emitcode ("mov","b,a");
10056                 pic16_emitcode("mov","a,@%s",rname);
10057                 break;
10058
10059             case FPOINTER:
10060                 pic16_emitcode ("mov","b,a");
10061                 pic16_emitcode("movx","a,@dptr");
10062                 break;
10063
10064             case GPOINTER:
10065                 pic16_emitcode ("push","b");
10066                 pic16_emitcode ("push","acc");
10067                 pic16_emitcode ("lcall","__gptrget");
10068                 pic16_emitcode ("pop","b");
10069                 break;
10070         }
10071
10072         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
10073         pic16_emitcode ("orl","a,b");
10074     }
10075
10076     if (p_type == GPOINTER)
10077         pic16_emitcode("pop","b");
10078
10079     switch (p_type) {
10080
10081     case POINTER:
10082         pic16_emitcode("mov","@%s,a",rname);
10083         break;
10084         
10085     case FPOINTER:
10086         pic16_emitcode("movx","@dptr,a");
10087         break;
10088         
10089     case GPOINTER:
10090         DEBUGpic16_emitcode(";lcall","__gptrput");
10091         break;                  
10092     }
10093 }
10094 /*-----------------------------------------------------------------*/
10095 /* genDataPointerSet - remat pointer to data space                 */
10096 /*-----------------------------------------------------------------*/
10097 static void genDataPointerSet(operand *right,
10098                               operand *result,
10099                               iCode *ic)
10100 {
10101     int size, offset = 0, resoffset=0 ;
10102
10103     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10104     pic16_aopOp(right,ic,FALSE);
10105
10106     size = AOP_SIZE(right);
10107
10108 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10109
10110 #if 0
10111     if ( AOP_TYPE(result) == AOP_PCODE) {
10112       fprintf(stderr,"genDataPointerSet   %s, %d\n",
10113               AOP(result)->aopu.pcop->name,
10114                 (AOP(result)->aopu.pcop->type == PO_DIR)?
10115               PCOR(AOP(result)->aopu.pcop)->instance:
10116               PCOI(AOP(result)->aopu.pcop)->offset);
10117     }
10118 #endif
10119
10120         if(AOP(result)->aopu.pcop->type == PO_DIR)
10121                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
10122
10123         while (size--) {
10124                 if (AOP_TYPE(right) == AOP_LIT) {
10125                   unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
10126
10127                         lit = lit >> (8*offset);
10128                         if(lit&0xff) {
10129                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
10130                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
10131                         } else {
10132                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
10133                         }
10134                 } else {
10135                         mov2w(AOP(right), offset);
10136                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
10137                 }
10138                 offset++;
10139                 resoffset++;
10140         }
10141
10142     pic16_freeAsmop(right,NULL,ic,TRUE);
10143 }
10144
10145
10146
10147 /*-----------------------------------------------------------------*/
10148 /* genNearPointerSet - pic16_emitcode for near pointer put         */
10149 /*-----------------------------------------------------------------*/
10150 static void genNearPointerSet (operand *right,
10151                                operand *result, 
10152                                iCode *ic)
10153 {
10154   asmop *aop = NULL;
10155   char *l;
10156   sym_link *retype;
10157   sym_link *ptype = operandType(result);
10158   sym_link *resetype;
10159     
10160         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10161         retype= getSpec(operandType(right));
10162         resetype = getSpec(operandType(result));
10163   
10164         pic16_aopOp(result,ic,FALSE);
10165     
10166         /* if the result is rematerializable &
10167          * in data space & not a bit variable */
10168         
10169         /* and result is not a bit variable */
10170         if (AOP_TYPE(result) == AOP_PCODE
10171 //              && AOP_TYPE(result) == AOP_IMMD
10172                 && DCL_TYPE(ptype) == POINTER
10173                 && !IS_BITFIELD(retype)
10174                 && !IS_BITFIELD(resetype)) {
10175
10176                 genDataPointerSet (right,result,ic);
10177                 pic16_freeAsmop(result,NULL,ic,TRUE);
10178           return;
10179         }
10180
10181         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10182         pic16_aopOp(right,ic,FALSE);
10183         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10184
10185         /* if the value is already in a pointer register
10186          * then don't need anything more */
10187         if (!AOP_INPREG(AOP(result))) {
10188                 /* otherwise get a free pointer register */
10189                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10190
10191                 if( (AOP_TYPE(result) == AOP_PCODE) 
10192                         && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10193                                 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10194                 {
10195                         pic16_loadFSR0( result );  // patch 10
10196                 } else {
10197                         // set up FSR0 with address of result
10198                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10199                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10200                 }
10201
10202         }
10203 //      else
10204 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10205
10206         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10207
10208         /* if bitfield then unpack the bits */
10209         if (IS_BITFIELD(resetype)) {
10210                 genPackBits (resetype, right, NULL, POINTER);
10211         } else {
10212                 /* we have can just get the values */
10213           int size = AOP_SIZE(right);
10214           int offset = 0 ;    
10215
10216                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10217                 while (size--) {
10218                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10219                         if (*l == '@' ) {
10220                                 //MOVA(l);
10221                                 //pic16_emitcode("mov","@%s,a",rname);
10222                                 pic16_emitcode("movf","indf0,w ;1");
10223                         } else {
10224
10225                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
10226                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
10227                                         if (size) {                                                                     // 
10228                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
10229                                         } else {                                                                        // 
10230                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
10231                                         }                                                                               // 
10232                                 } else { // no literal                                                                  // 
10233                                         if(size) {                                                                      // 
10234                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10235                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10236                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
10237                                         } else {                                                                        // 
10238                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10239                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10240                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
10241                                         }                                                                               //
10242                                 }                                                                                       // patch 10
10243                         }
10244                         offset++;
10245                 }
10246         }
10247
10248         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10249         /* now some housekeeping stuff */
10250         if (aop) {
10251                 /* we had to allocate for this iCode */
10252                 pic16_freeAsmop(NULL,aop,ic,TRUE);
10253         } else { 
10254                 /* we did not allocate which means left
10255                  * already in a pointer register, then
10256                  * if size > 0 && this could be used again
10257                  * we have to point it back to where it 
10258                  * belongs */
10259                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10260                 if (AOP_SIZE(right) > 1
10261                         && !OP_SYMBOL(result)->remat
10262                         && ( OP_SYMBOL(result)->liveTo > ic->seq
10263                                 || ic->depth )) {
10264
10265                   int size = AOP_SIZE(right) - 1;
10266
10267                         while (size--)
10268                                 pic16_emitcode("decf","fsr0,f");
10269                         //pic16_emitcode("dec","%s",rname);
10270                 }
10271         }
10272
10273         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10274         /* done */
10275 //release:
10276         pic16_freeAsmop(right,NULL,ic,TRUE);
10277         pic16_freeAsmop(result,NULL,ic,TRUE);
10278 }
10279
10280 /*-----------------------------------------------------------------*/
10281 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
10282 /*-----------------------------------------------------------------*/
10283 static void genPagedPointerSet (operand *right,
10284                                operand *result, 
10285                                iCode *ic)
10286 {
10287     asmop *aop = NULL;
10288     regs *preg = NULL ;
10289     char *rname , *l;
10290     sym_link *retype;
10291        
10292     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10293
10294     retype= getSpec(operandType(right));
10295     
10296     pic16_aopOp(result,ic,FALSE);
10297     
10298     /* if the value is already in a pointer register
10299        then don't need anything more */
10300     if (!AOP_INPREG(AOP(result))) {
10301         /* otherwise get a free pointer register */
10302         aop = newAsmop(0);
10303         preg = getFreePtr(ic,&aop,FALSE);
10304         pic16_emitcode("mov","%s,%s",
10305                 preg->name,
10306                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10307         rname = preg->name ;
10308     } else
10309         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10310     
10311     pic16_freeAsmop(result,NULL,ic,TRUE);
10312     pic16_aopOp (right,ic,FALSE);
10313
10314     /* if bitfield then unpack the bits */
10315     if (IS_BITFIELD(retype)) 
10316         genPackBits (retype,right,rname,PPOINTER);
10317     else {
10318         /* we have can just get the values */
10319         int size = AOP_SIZE(right);
10320         int offset = 0 ;        
10321         
10322         while (size--) {
10323             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10324             
10325             MOVA(l);
10326             pic16_emitcode("movx","@%s,a",rname);
10327
10328             if (size)
10329                 pic16_emitcode("inc","%s",rname);
10330
10331             offset++;
10332         }
10333     }
10334     
10335     /* now some housekeeping stuff */
10336     if (aop) {
10337         /* we had to allocate for this iCode */
10338         pic16_freeAsmop(NULL,aop,ic,TRUE);
10339     } else { 
10340         /* we did not allocate which means left
10341            already in a pointer register, then
10342            if size > 0 && this could be used again
10343            we have to point it back to where it 
10344            belongs */
10345         if (AOP_SIZE(right) > 1 &&
10346             !OP_SYMBOL(result)->remat &&
10347             ( OP_SYMBOL(result)->liveTo > ic->seq ||
10348               ic->depth )) {
10349             int size = AOP_SIZE(right) - 1;
10350             while (size--)
10351                 pic16_emitcode("dec","%s",rname);
10352         }
10353     }
10354
10355     /* done */
10356     pic16_freeAsmop(right,NULL,ic,TRUE);
10357     
10358         
10359 }
10360
10361 /*-----------------------------------------------------------------*/
10362 /* genFarPointerSet - set value from far space                     */
10363 /*-----------------------------------------------------------------*/
10364 static void genFarPointerSet (operand *right,
10365                               operand *result, iCode *ic)
10366 {
10367     int size, offset ;
10368     sym_link *retype = getSpec(operandType(right));
10369
10370     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10371     pic16_aopOp(result,ic,FALSE);
10372
10373     /* if the operand is already in dptr 
10374     then we do nothing else we move the value to dptr */
10375     if (AOP_TYPE(result) != AOP_STR) {
10376         /* if this is remateriazable */
10377         if (AOP_TYPE(result) == AOP_IMMD)
10378             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10379         else { /* we need to get it byte by byte */
10380             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10381             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10382             if (options.model == MODEL_FLAT24)
10383             {
10384                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10385             }
10386         }
10387     }
10388     /* so dptr know contains the address */
10389     pic16_freeAsmop(result,NULL,ic,TRUE);
10390     pic16_aopOp(right,ic,FALSE);
10391
10392     /* if bit then unpack */
10393     if (IS_BITFIELD(retype)) 
10394         genPackBits(retype,right,"dptr",FPOINTER);
10395     else {
10396         size = AOP_SIZE(right);
10397         offset = 0 ;
10398
10399         while (size--) {
10400             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10401             MOVA(l);
10402             pic16_emitcode("movx","@dptr,a");
10403             if (size)
10404                 pic16_emitcode("inc","dptr");
10405         }
10406     }
10407
10408     pic16_freeAsmop(right,NULL,ic,TRUE);
10409 }
10410
10411 /*-----------------------------------------------------------------*/
10412 /* genGenPointerSet - set value from generic pointer space         */
10413 /*-----------------------------------------------------------------*/
10414 static void genGenPointerSet (operand *right,
10415                               operand *result, iCode *ic)
10416 {
10417         int i, size, offset, lit;
10418         sym_link *retype = getSpec(operandType(right));
10419
10420         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10421
10422         pic16_aopOp(result,ic,FALSE);
10423         pic16_aopOp(right,ic,FALSE);
10424         size = AOP_SIZE(right);
10425         offset = 0;
10426
10427         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10428
10429         /* if the operand is already in dptr 
10430                 then we do nothing else we move the value to dptr */
10431         if (AOP_TYPE(result) != AOP_STR) {
10432                 /* if this is remateriazable */
10433                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10434                 // WARNING: anythig until "else" is untested!
10435                 if (AOP_TYPE(result) == AOP_IMMD) {
10436                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10437                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10438                         // load FSR0 from immediate
10439                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10440                         offset = 0;
10441                         while(size--) {
10442                                 if(size) {
10443                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10444                                 } else {
10445                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10446                                 }
10447                                 offset++;
10448                         }
10449                         goto release;
10450                 }
10451                 else { /* we need to get it byte by byte */
10452                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10453                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10454
10455                         // set up FSR0 with address of result
10456                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10457                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10458
10459                         /* hack hack! see if this the FSR. If so don't load W */
10460                         if(AOP_TYPE(right) != AOP_ACC) {
10461
10462                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10463
10464                                 if(AOP_TYPE(right) == AOP_LIT)
10465                                 {
10466                                         // copy literal
10467                                         // note: pic16_popGet handles sign extension
10468                                         for(i=0;i<size;i++) {
10469                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10470                                                 if(i < size-1)
10471                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10472                                                 else
10473                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10474                                         }
10475                                 } else {
10476                                         // copy regs
10477
10478                                         for(i=0;i<size;i++) {
10479                                                 if(i < size-1)
10480                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10481                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
10482                                                 else
10483                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10484                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
10485                                         }
10486                                 }
10487                                 goto release;
10488                         } 
10489                         // right = ACC
10490                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10491                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10492                         goto release;
10493         } // if (AOP_TYPE(result) != AOP_IMMD)
10494
10495         } // if (AOP_TYPE(result) != AOP_STR)
10496         /* so dptr know contains the address */
10497
10498
10499         /* if bit then unpack */
10500         if (IS_BITFIELD(retype)) 
10501                 genPackBits(retype,right,"dptr",GPOINTER);
10502         else {
10503                 size = AOP_SIZE(right);
10504                 offset = 0 ;
10505
10506                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
10507
10508                 // set up FSR0 with address of result
10509                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10510                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10511         
10512                 while (size--) {
10513                         if (AOP_TYPE(right) == AOP_LIT) {
10514                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10515                                 if (size) {
10516                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10517                                 } else {
10518                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10519                                 }
10520                         } else { // no literal
10521                                 if(size) {
10522                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10523                                 } else {
10524                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10525                                 }
10526                         }
10527                         offset++;
10528                 }
10529         }
10530
10531         release:
10532         pic16_freeAsmop(right,NULL,ic,TRUE);
10533         pic16_freeAsmop(result,NULL,ic,TRUE);
10534 }
10535
10536 /*-----------------------------------------------------------------*/
10537 /* genPointerSet - stores the value into a pointer location        */
10538 /*-----------------------------------------------------------------*/
10539 static void genPointerSet (iCode *ic)
10540 {    
10541     operand *right, *result ;
10542     sym_link *type, *etype;
10543     int p_type;
10544
10545     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10546
10547     right = IC_RIGHT(ic);
10548     result = IC_RESULT(ic) ;
10549
10550     /* depending on the type of pointer we need to
10551     move it to the correct pointer register */
10552     type = operandType(result);
10553     etype = getSpec(type);
10554     /* if left is of type of pointer then it is simple */
10555     if (IS_PTR(type) && !IS_FUNC(type->next)) {
10556         p_type = DCL_TYPE(type);
10557     }
10558     else {
10559         /* we have to go by the storage class */
10560         p_type = PTR_TYPE(SPEC_OCLS(etype));
10561
10562 /*      if (SPEC_OCLS(etype)->codesp ) { */
10563 /*          p_type = CPOINTER ;  */
10564 /*      } */
10565 /*      else */
10566 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10567 /*              p_type = FPOINTER ; */
10568 /*          else */
10569 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10570 /*                  p_type = PPOINTER ; */
10571 /*              else */
10572 /*                  if (SPEC_OCLS(etype) == idata ) */
10573 /*                      p_type = IPOINTER ; */
10574 /*                  else */
10575 /*                      p_type = POINTER ; */
10576     }
10577
10578     /* now that we have the pointer type we assign
10579     the pointer values */
10580     switch (p_type) {
10581
10582     case POINTER:
10583     case IPOINTER:
10584         genNearPointerSet (right,result,ic);
10585         break;
10586
10587     case PPOINTER:
10588         genPagedPointerSet (right,result,ic);
10589         break;
10590
10591     case FPOINTER:
10592         genFarPointerSet (right,result,ic);
10593         break;
10594
10595     case GPOINTER:
10596         genGenPointerSet (right,result,ic);
10597         break;
10598
10599     default:
10600       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10601               "genPointerSet: illegal pointer type");
10602     }
10603 }
10604
10605 /*-----------------------------------------------------------------*/
10606 /* genIfx - generate code for Ifx statement                        */
10607 /*-----------------------------------------------------------------*/
10608 static void genIfx (iCode *ic, iCode *popIc)
10609 {
10610   operand *cond = IC_COND(ic);
10611   int isbit =0;
10612
10613   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10614
10615   pic16_aopOp(cond,ic,FALSE);
10616
10617   /* get the value into acc */
10618   if (AOP_TYPE(cond) != AOP_CRY)
10619     pic16_toBoolean(cond);
10620   else
10621     isbit = 1;
10622   /* the result is now in the accumulator */
10623   pic16_freeAsmop(cond,NULL,ic,TRUE);
10624
10625   /* if there was something to be popped then do it */
10626   if (popIc)
10627     genIpop(popIc);
10628
10629   /* if the condition is  a bit variable */
10630   if (isbit && IS_ITEMP(cond) && 
10631       SPIL_LOC(cond)) {
10632     genIfxJump(ic,SPIL_LOC(cond)->rname);
10633     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10634   }
10635   else {
10636     if (isbit && !IS_ITEMP(cond))
10637       genIfxJump(ic,OP_SYMBOL(cond)->rname);
10638     else
10639       genIfxJump(ic,"a");
10640   }
10641   ic->generated = 1;
10642
10643 }
10644
10645 /*-----------------------------------------------------------------*/
10646 /* genAddrOf - generates code for address of                       */
10647 /*-----------------------------------------------------------------*/
10648 static void genAddrOf (iCode *ic)
10649 {
10650   operand *result, *left;
10651   int size;
10652   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
10653   pCodeOp *pcop0, *pcop1, *pcop2;
10654
10655         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10656
10657         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10658         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10659
10660         sym = OP_SYMBOL( left );
10661
10662         size = AOP_SIZE(IC_RESULT(ic));
10663
10664
10665         if(sym->onStack) {
10666                 DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
10667         
10668                 return;
10669         }
10670         
10671 //      if(pic16_debug_verbose) {
10672 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10673 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10674 //      }
10675         
10676         /* Assume that what we want the address of is in data space
10677          * since there is no stack on the PIC, yet! -- VR */
10678         /* low */
10679         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10680
10681         /* high */
10682         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10683         
10684         /* upper */
10685         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10686         
10687
10688         if (size == 3) {
10689                 pic16_emitpcode(POC_MOVLW, pcop0);
10690                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10691                 pic16_emitpcode(POC_MOVLW, pcop1);
10692                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10693                 pic16_emitpcode(POC_MOVLW, pcop2);
10694                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10695         } else
10696         if (size == 2) {
10697                 pic16_emitpcode(POC_MOVLW, pcop0);
10698                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10699                 pic16_emitpcode(POC_MOVLW, pcop1);
10700                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10701         } else {
10702                 pic16_emitpcode(POC_MOVLW, pcop0);
10703                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10704         }
10705
10706         pic16_freeAsmop(result,NULL,ic,TRUE);
10707         pic16_freeAsmop(left, NULL, ic, FALSE);
10708 }
10709
10710
10711 #if 0
10712 /*-----------------------------------------------------------------*/
10713 /* genFarFarAssign - assignment when both are in far space         */
10714 /*-----------------------------------------------------------------*/
10715 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10716 {
10717     int size = AOP_SIZE(right);
10718     int offset = 0;
10719     char *l ;
10720     /* first push the right side on to the stack */
10721     while (size--) {
10722         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10723         MOVA(l);
10724         pic16_emitcode ("push","acc");
10725     }
10726     
10727     pic16_freeAsmop(right,NULL,ic,FALSE);
10728     /* now assign DPTR to result */
10729     pic16_aopOp(result,ic,FALSE);
10730     size = AOP_SIZE(result);
10731     while (size--) {
10732         pic16_emitcode ("pop","acc");
10733         pic16_aopPut(AOP(result),"a",--offset);
10734     }
10735     pic16_freeAsmop(result,NULL,ic,FALSE);
10736         
10737 }
10738 #endif
10739
10740 /*-----------------------------------------------------------------*/
10741 /* genAssign - generate code for assignment                        */
10742 /*-----------------------------------------------------------------*/
10743 static void genAssign (iCode *ic)
10744 {
10745   operand *result, *right;
10746   int size, offset,know_W;
10747   unsigned long lit = 0L;
10748
10749   result = IC_RESULT(ic);
10750   right  = IC_RIGHT(ic) ;
10751
10752   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10753   
10754   /* if they are the same */
10755   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10756     return ;
10757
10758   pic16_aopOp(right,ic,FALSE);
10759   pic16_aopOp(result,ic,TRUE);
10760
10761   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10762
10763   /* if they are the same registers */
10764   if (pic16_sameRegs(AOP(right),AOP(result)))
10765     goto release;
10766
10767   /* if the result is a bit */
10768   if (AOP_TYPE(result) == AOP_CRY) {
10769     /* if the right size is a literal then
10770        we know what the value is */
10771     if (AOP_TYPE(right) == AOP_LIT) {
10772           
10773       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10774                   pic16_popGet(AOP(result),0));
10775
10776       if (((int) operandLitValue(right))) 
10777         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10778                        AOP(result)->aopu.aop_dir,
10779                        AOP(result)->aopu.aop_dir);
10780       else
10781         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10782                        AOP(result)->aopu.aop_dir,
10783                        AOP(result)->aopu.aop_dir);
10784       goto release;
10785     }
10786
10787     /* the right is also a bit variable */
10788     if (AOP_TYPE(right) == AOP_CRY) {
10789       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10790       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10791       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10792
10793       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10794                      AOP(result)->aopu.aop_dir,
10795                      AOP(result)->aopu.aop_dir);
10796       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10797                      AOP(right)->aopu.aop_dir,
10798                      AOP(right)->aopu.aop_dir);
10799       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10800                      AOP(result)->aopu.aop_dir,
10801                      AOP(result)->aopu.aop_dir);
10802       goto release ;
10803     }
10804
10805     /* we need to or */
10806     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10807     pic16_toBoolean(right);
10808     emitSKPZ;
10809     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10810     //pic16_aopPut(AOP(result),"a",0);
10811     goto release ;
10812   }
10813
10814   /* bit variables done */
10815   /* general case */
10816   size = AOP_SIZE(result);
10817   offset = 0 ;
10818
10819   if(AOP_TYPE(right) == AOP_LIT) {
10820         if(!IS_FLOAT(operandType( right )))
10821                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10822         else {
10823            union {
10824               unsigned long lit_int;
10825               float lit_float;
10826             } info;
10827         
10828                 /* take care if literal is a float */
10829                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
10830                 lit = info.lit_int;
10831         }
10832   }
10833
10834 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
10835 //                      sizeof(unsigned long int), sizeof(float));
10836
10837   if(AOP_TYPE(right) != AOP_LIT
10838         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
10839         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
10840
10841         // set up table pointer
10842         if( (AOP_TYPE(right) == AOP_PCODE)
10843                 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
10844                 || (AOP(right)->aopu.pcop->type == PO_DIR)))
10845         {
10846                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
10847                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10848                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
10849                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10850                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
10851                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10852         } else {
10853                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
10854                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
10855                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
10856                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
10857                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
10858                                 pic16_popCopyReg(&pic16_pc_tblptru)));
10859         }
10860
10861         size = min(AOP_SIZE(right), AOP_SIZE(result));
10862         while(size--) {
10863                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10864                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
10865                         pic16_popGet(AOP(result),offset)));
10866                 offset++;
10867         }
10868
10869         if(AOP_SIZE(result) > AOP_SIZE(right)) {
10870                 size = AOP_SIZE(result) - AOP_SIZE(right);
10871                 while(size--) {
10872                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
10873                         offset++;
10874                 }
10875         }
10876         goto release;
10877   }
10878
10879
10880
10881 /* VR - What is this?! */
10882   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10883   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10884     if(aopIdx(AOP(result),0) == 4) {
10885   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10886         assert(0);
10887       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10888       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10889       goto release;
10890     } else
10891 //      assert(0);
10892       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10893   }
10894
10895   know_W=-1;
10896   while (size--) {
10897   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10898     if(AOP_TYPE(right) == AOP_LIT) {
10899       if(lit&0xff) {
10900         if(know_W != (lit&0xff))
10901           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10902         know_W = lit&0xff;
10903         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10904       } else
10905         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10906
10907       lit >>= 8;
10908
10909     } else if (AOP_TYPE(right) == AOP_CRY) {
10910       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10911       if(offset == 0) {
10912         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10913         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10914       }
10915     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10916         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10917         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10918     } else {
10919   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10920
10921 #if 1
10922         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10923            normally should work, but mind that the W register live range
10924            is not checked, so if the code generator assumes that the W
10925            is already loaded after such a pair, wrong code will be generated.
10926            
10927            Checking the live range is the next step.
10928            This is experimental code yet and has not been fully tested yet.
10929            USE WITH CARE. Revert to old code by setting 0 to the condition above.
10930            Vangelis Rokas 030603 (vrokas@otenet.gr) */
10931            
10932         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10933 #else   
10934         /* This is the old code, which is assumed(?!) that works fine(!?) */
10935
10936         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10937         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10938 #endif
10939     }
10940             
10941     offset++;
10942   }
10943
10944     
10945  release:
10946   pic16_freeAsmop (right,NULL,ic,FALSE);
10947   pic16_freeAsmop (result,NULL,ic,TRUE);
10948 }   
10949
10950 /*-----------------------------------------------------------------*/
10951 /* genJumpTab - generates code for jump table                       */
10952 /*-----------------------------------------------------------------*/
10953 static void genJumpTab (iCode *ic)
10954 {
10955     symbol *jtab;
10956     char *l;
10957
10958     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10959
10960     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10961     /* get the condition into accumulator */
10962     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10963     MOVA(l);
10964     /* multiply by three */
10965     pic16_emitcode("add","a,acc");
10966     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10967
10968     jtab = newiTempLabel(NULL);
10969     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10970     pic16_emitcode("jmp","@a+dptr");
10971     pic16_emitcode("","%05d_DS_:",jtab->key+100);
10972
10973     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10974     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10975     emitSKPNC;
10976     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10977     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10978     pic16_emitpLabel(jtab->key);
10979
10980     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10981
10982     /* now generate the jump labels */
10983     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10984          jtab = setNextItem(IC_JTLABELS(ic))) {
10985         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10986         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10987         
10988     }
10989
10990 }
10991
10992 /*-----------------------------------------------------------------*/
10993 /* genMixedOperation - gen code for operators between mixed types  */
10994 /*-----------------------------------------------------------------*/
10995 /*
10996   TSD - Written for the PIC port - but this unfortunately is buggy.
10997   This routine is good in that it is able to efficiently promote 
10998   types to different (larger) sizes. Unfortunately, the temporary
10999   variables that are optimized out by this routine are sometimes
11000   used in other places. So until I know how to really parse the 
11001   iCode tree, I'm going to not be using this routine :(.
11002 */
11003 static int genMixedOperation (iCode *ic)
11004 {
11005 #if 0
11006   operand *result = IC_RESULT(ic);
11007   sym_link *ctype = operandType(IC_LEFT(ic));
11008   operand *right = IC_RIGHT(ic);
11009   int ret = 0;
11010   int big,small;
11011   int offset;
11012
11013   iCode *nextic;
11014   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
11015
11016   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11017
11018   nextic = ic->next;
11019   if(!nextic)
11020     return 0;
11021
11022   nextright = IC_RIGHT(nextic);
11023   nextleft  = IC_LEFT(nextic);
11024   nextresult = IC_RESULT(nextic);
11025
11026   pic16_aopOp(right,ic,FALSE);
11027   pic16_aopOp(result,ic,FALSE);
11028   pic16_aopOp(nextright,  nextic, FALSE);
11029   pic16_aopOp(nextleft,   nextic, FALSE);
11030   pic16_aopOp(nextresult, nextic, FALSE);
11031
11032   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
11033
11034     operand *t = right;
11035     right = nextright;
11036     nextright = t; 
11037
11038     pic16_emitcode(";remove right +","");
11039
11040   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
11041 /*
11042     operand *t = right;
11043     right = nextleft;
11044     nextleft = t; 
11045 */
11046     pic16_emitcode(";remove left +","");
11047   } else
11048     return 0;
11049
11050   big = AOP_SIZE(nextleft);
11051   small = AOP_SIZE(nextright);
11052
11053   switch(nextic->op) {
11054
11055   case '+':
11056     pic16_emitcode(";optimize a +","");
11057     /* if unsigned or not an integral type */
11058     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
11059       pic16_emitcode(";add a bit to something","");
11060     } else {
11061
11062       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
11063
11064       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
11065         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
11066         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
11067       } else
11068         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
11069
11070       offset = 0;
11071       while(--big) {
11072
11073         offset++;
11074
11075         if(--small) {
11076           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11077             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11078             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11079           }
11080
11081           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11082           emitSKPNC;
11083           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11084                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
11085                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
11086           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11087           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
11088
11089         } else {
11090           pic16_emitcode("rlf","known_zero,w");
11091
11092           /*
11093             if right is signed
11094               btfsc  right,7
11095                addlw ff
11096           */
11097           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11098             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11099             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11100           } else {
11101             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11102           }
11103         }
11104       }
11105       ret = 1;
11106     }
11107   }
11108   ret = 1;
11109
11110 release:
11111   pic16_freeAsmop(right,NULL,ic,TRUE);
11112   pic16_freeAsmop(result,NULL,ic,TRUE);
11113   pic16_freeAsmop(nextright,NULL,ic,TRUE);
11114   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
11115   if(ret)
11116     nextic->generated = 1;
11117
11118   return ret;
11119 #else
11120   return 0;
11121 #endif
11122 }
11123 /*-----------------------------------------------------------------*/
11124 /* genCast - gen code for casting                                  */
11125 /*-----------------------------------------------------------------*/
11126 static void genCast (iCode *ic)
11127 {
11128   operand *result = IC_RESULT(ic);
11129   sym_link *ctype = operandType(IC_LEFT(ic));
11130   sym_link *rtype = operandType(IC_RIGHT(ic));
11131   operand *right = IC_RIGHT(ic);
11132   int size, offset ;
11133
11134         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11135         /* if they are equivalent then do nothing */
11136         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
11137                 return ;
11138
11139         pic16_aopOp(right,ic,FALSE) ;
11140         pic16_aopOp(result,ic,FALSE);
11141
11142         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11143
11144         /* if the result is a bit */
11145         if (AOP_TYPE(result) == AOP_CRY) {
11146         
11147                 /* if the right size is a literal then
11148                  * we know what the value is */
11149                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11150
11151                 if (AOP_TYPE(right) == AOP_LIT) {
11152                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
11153                                 pic16_popGet(AOP(result),0));
11154
11155                         if (((int) operandLitValue(right))) 
11156                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
11157                                         AOP(result)->aopu.aop_dir,
11158                                         AOP(result)->aopu.aop_dir);
11159                         else
11160                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
11161                                         AOP(result)->aopu.aop_dir,
11162                                         AOP(result)->aopu.aop_dir);
11163                         goto release;
11164                 }
11165
11166                 /* the right is also a bit variable */
11167                 if (AOP_TYPE(right) == AOP_CRY) {
11168                         emitCLRC;
11169                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
11170
11171                         pic16_emitcode("clrc","");
11172                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11173                                 AOP(right)->aopu.aop_dir,
11174                                 AOP(right)->aopu.aop_dir);
11175                         pic16_aopPut(AOP(result),"c",0);
11176                         goto release ;
11177                 }
11178
11179                 /* we need to or */
11180                 if (AOP_TYPE(right) == AOP_REG) {
11181                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
11182                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
11183                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
11184                 }
11185                 pic16_toBoolean(right);
11186                 pic16_aopPut(AOP(result),"a",0);
11187                 goto release ;
11188         }
11189
11190         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
11191           int offset = 1;
11192
11193                 size = AOP_SIZE(result);
11194
11195                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11196
11197                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
11198                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
11199                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
11200
11201                 while (size--)
11202                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11203
11204                 goto release;
11205         }
11206
11207         /* if they are the same size : or less */
11208         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
11209
11210                 /* if they are in the same place */
11211                 if (pic16_sameRegs(AOP(right),AOP(result)))
11212                         goto release;
11213
11214                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11215 #if 0
11216                 if (IS_PTR_CONST(rtype))
11217 #else
11218                 if (IS_CODEPTR(rtype))
11219 #endif
11220                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
11221
11222 #if 0
11223                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
11224 #else
11225                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
11226 #endif
11227                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
11228
11229 #if 0
11230                 if(AOP_TYPE(right) == AOP_IMMD) {
11231                   pCodeOp *pcop0, *pcop1, *pcop2;
11232                   symbol *sym = OP_SYMBOL( right );
11233
11234                         size = AOP_SIZE(result);
11235                         /* low */
11236                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11237                         /* high */
11238                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11239                         /* upper */
11240                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11241         
11242                         if (size == 3) {
11243                                 pic16_emitpcode(POC_MOVLW, pcop0);
11244                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11245                                 pic16_emitpcode(POC_MOVLW, pcop1);
11246                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11247                                 pic16_emitpcode(POC_MOVLW, pcop2);
11248                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11249                         } else
11250                         if (size == 2) {
11251                                 pic16_emitpcode(POC_MOVLW, pcop0);
11252                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11253                                 pic16_emitpcode(POC_MOVLW, pcop1);
11254                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11255                         } else {
11256                                 pic16_emitpcode(POC_MOVLW, pcop0);
11257                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11258                         }
11259                 } else
11260 #endif
11261                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11262                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
11263                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11264                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
11265                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11266                         if(AOP_SIZE(result) <2)
11267                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
11268                 } else {
11269                         /* if they in different places then copy */
11270                         size = AOP_SIZE(result);
11271                         offset = 0 ;
11272                         while (size--) {
11273                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11274                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11275                                 offset++;
11276                         }
11277                 }
11278                 goto release;
11279         }
11280
11281         /* if the result is of type pointer */
11282         if (IS_PTR(ctype)) {
11283           int p_type;
11284           sym_link *type = operandType(right);
11285           sym_link *etype = getSpec(type);
11286
11287                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
11288
11289                 /* pointer to generic pointer */
11290                 if (IS_GENPTR(ctype)) {
11291                   char *l = zero;
11292             
11293                         if (IS_PTR(type)) 
11294                                 p_type = DCL_TYPE(type);
11295                         else {
11296                 /* we have to go by the storage class */
11297                 p_type = PTR_TYPE(SPEC_OCLS(etype));
11298
11299 /*              if (SPEC_OCLS(etype)->codesp )  */
11300 /*                  p_type = CPOINTER ;  */
11301 /*              else */
11302 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11303 /*                      p_type = FPOINTER ; */
11304 /*                  else */
11305 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11306 /*                          p_type = PPOINTER; */
11307 /*                      else */
11308 /*                          if (SPEC_OCLS(etype) == idata ) */
11309 /*                              p_type = IPOINTER ; */
11310 /*                          else */
11311 /*                              p_type = POINTER ; */
11312             }
11313                 
11314             /* the first two bytes are known */
11315       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
11316             size = GPTRSIZE - 1; 
11317             offset = 0 ;
11318             while (size--) {
11319               if(offset < AOP_SIZE(right)) {
11320       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
11321                 if ((AOP_TYPE(right) == AOP_PCODE) && 
11322                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11323                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11324                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11325                 } else { 
11326                   pic16_aopPut(AOP(result),
11327                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11328                          offset);
11329                 }
11330               } else 
11331                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11332               offset++;
11333             }
11334             /* the last byte depending on type */
11335             switch (p_type) {
11336             case IPOINTER:
11337             case POINTER:
11338                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11339                 break;
11340             case FPOINTER:
11341               pic16_emitcode(";BUG!? ","%d",__LINE__);
11342                 l = one;
11343                 break;
11344             case CPOINTER:
11345               pic16_emitcode(";BUG!? ","%d",__LINE__);
11346                 l = "#0x02";
11347                 break;                          
11348             case PPOINTER:
11349               pic16_emitcode(";BUG!? ","%d",__LINE__);
11350                 l = "#0x03";
11351                 break;
11352                 
11353             default:
11354                 /* this should never happen */
11355                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11356                        "got unknown pointer type");
11357                 exit(1);
11358             }
11359             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
11360             goto release ;
11361         }
11362         
11363         /* just copy the pointers */
11364         size = AOP_SIZE(result);
11365         offset = 0 ;
11366         while (size--) {
11367             pic16_aopPut(AOP(result),
11368                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11369                    offset);
11370             offset++;
11371         }
11372         goto release ;
11373     }
11374     
11375
11376
11377     /* so we now know that the size of destination is greater
11378     than the size of the source.
11379     Now, if the next iCode is an operator then we might be
11380     able to optimize the operation without performing a cast.
11381     */
11382     if(genMixedOperation(ic))
11383       goto release;
11384
11385     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11386     
11387     /* we move to result for the size of source */
11388     size = AOP_SIZE(right);
11389     offset = 0 ;
11390     while (size--) {
11391       pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
11392 //      pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
11393 //      pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
11394       offset++;
11395     }
11396
11397     /* now depending on the sign of the destination */
11398     size = AOP_SIZE(result) - AOP_SIZE(right);
11399     /* if unsigned or not an integral type */
11400     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11401       while (size--)
11402         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11403     } else {
11404       /* we need to extend the sign :( */
11405
11406       if(size == 1) {
11407         /* Save one instruction of casting char to int */
11408         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
11409         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11410         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
11411       } else {
11412         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11413
11414         if(offset)
11415           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11416         else
11417           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11418         
11419         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
11420
11421         while (size--)
11422           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
11423       }
11424     }
11425
11426 release:
11427     pic16_freeAsmop(right,NULL,ic,TRUE);
11428     pic16_freeAsmop(result,NULL,ic,TRUE);
11429
11430 }
11431
11432 /*-----------------------------------------------------------------*/
11433 /* genDjnz - generate decrement & jump if not zero instrucion      */
11434 /*-----------------------------------------------------------------*/
11435 static int genDjnz (iCode *ic, iCode *ifx)
11436 {
11437     symbol *lbl, *lbl1;
11438     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11439
11440     if (!ifx)
11441         return 0;
11442     
11443     /* if the if condition has a false label
11444        then we cannot save */
11445     if (IC_FALSE(ifx))
11446         return 0;
11447
11448     /* if the minus is not of the form 
11449        a = a - 1 */
11450     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11451         !IS_OP_LITERAL(IC_RIGHT(ic)))
11452         return 0;
11453
11454     if (operandLitValue(IC_RIGHT(ic)) != 1)
11455         return 0;
11456
11457     /* if the size of this greater than one then no
11458        saving */
11459     if (getSize(operandType(IC_RESULT(ic))) > 1)
11460         return 0;
11461
11462     /* otherwise we can save BIG */
11463     lbl = newiTempLabel(NULL);
11464     lbl1= newiTempLabel(NULL);
11465
11466     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11467     
11468     if (IS_AOP_PREG(IC_RESULT(ic))) {
11469         pic16_emitcode("dec","%s",
11470                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11471         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11472         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11473     } else {    
11474
11475
11476       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11477       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11478
11479       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11480       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
11481
11482     }
11483 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11484 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11485 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11486 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11487
11488     
11489     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11490     ifx->generated = 1;
11491     return 1;
11492 }
11493
11494 /*-----------------------------------------------------------------*/
11495 /* genReceive - generate code for a receive iCode                  */
11496 /*-----------------------------------------------------------------*/
11497 static void genReceive (iCode *ic)
11498 {    
11499         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11500
11501 #if 0
11502         fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
11503                 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
11504 #endif
11505 //      pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
11506
11507         if (isOperandInFarSpace(IC_RESULT(ic)) &&
11508                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11509                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11510
11511           int size = getSize(operandType(IC_RESULT(ic)));
11512           int offset =  pic16_fReturnSizePic - size;
11513
11514                 assert( 0 );
11515                 while (size--) {
11516                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11517                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11518                         offset++;
11519                 }
11520
11521                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
11522
11523                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11524                 size = AOP_SIZE(IC_RESULT(ic));
11525                 offset = 0;
11526                 while (size--) {
11527                         pic16_emitcode ("pop","acc");
11528                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11529                 }
11530         } else {
11531                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
11532
11533                 _G.accInUse++;
11534                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11535                 _G.accInUse--;
11536                 assignResultValue(IC_RESULT(ic), 0);
11537         }
11538
11539         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11540 }
11541
11542 /*-----------------------------------------------------------------*/
11543 /* genDummyRead - generate code for dummy read of volatiles        */
11544 /*-----------------------------------------------------------------*/
11545 static void
11546 genDummyRead (iCode * ic)
11547 {
11548   pic16_emitcode ("; genDummyRead","");
11549   pic16_emitcode ("; not implemented","");
11550
11551   ic = ic;
11552 }
11553
11554 /*-----------------------------------------------------------------*/
11555 /* genpic16Code - generate code for pic16 based controllers        */
11556 /*-----------------------------------------------------------------*/
11557 /*
11558  * At this point, ralloc.c has gone through the iCode and attempted
11559  * to optimize in a way suitable for a PIC. Now we've got to generate
11560  * PIC instructions that correspond to the iCode.
11561  *
11562  * Once the instructions are generated, we'll pass through both the
11563  * peep hole optimizer and the pCode optimizer.
11564  *-----------------------------------------------------------------*/
11565
11566 void genpic16Code (iCode *lic)
11567 {
11568     iCode *ic;
11569     int cln = 0;
11570
11571     lineHead = lineCurr = NULL;
11572
11573     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11574     pic16_addpBlock(pb);
11575
11576 #if 0
11577     /* if debug information required */
11578     if (options.debug && currFunc) {
11579       if (currFunc) {
11580         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11581       }
11582     }
11583 #endif
11584
11585     for (ic = lic ; ic ; ic = ic->next ) {
11586
11587       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11588         if ( cln != ic->lineno ) {
11589             if ( options.debug ) {
11590               debugFile->writeCLine (ic);
11591             }
11592             
11593             if(!options.noCcodeInAsm) {
11594                 pic16_addpCode2pBlock(pb,
11595                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
11596                                 printCLine(ic->filename, ic->lineno)));
11597             }
11598
11599             cln = ic->lineno ;
11600         }
11601         
11602         if(options.iCodeInAsm) {
11603                 char *l;
11604                 /* insert here code to print iCode as comment */
11605                 l = Safe_strdup(printILine(ic));
11606                 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11607         }
11608         
11609         /* if the result is marked as
11610            spilt and rematerializable or code for
11611            this has already been generated then
11612            do nothing */
11613         if (resultRemat(ic) || ic->generated ) 
11614             continue ;
11615         
11616         /* depending on the operation */
11617         switch (ic->op) {
11618         case '!' :
11619             pic16_genNot(ic);
11620             break;
11621             
11622         case '~' :
11623             pic16_genCpl(ic);
11624             break;
11625             
11626         case UNARYMINUS:
11627             genUminus (ic);
11628             break;
11629             
11630         case IPUSH:
11631             genIpush (ic);
11632             break;
11633             
11634         case IPOP:
11635             /* IPOP happens only when trying to restore a 
11636                spilt live range, if there is an ifx statement
11637                following this pop then the if statement might
11638                be using some of the registers being popped which
11639                would destroy the contents of the register so
11640                we need to check for this condition and handle it */
11641             if (ic->next            && 
11642                 ic->next->op == IFX &&
11643                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
11644                 genIfx (ic->next,ic);
11645             else
11646                 genIpop (ic);
11647             break; 
11648             
11649         case CALL:
11650             genCall (ic);
11651             break;
11652             
11653         case PCALL:
11654             genPcall (ic);
11655             break;
11656             
11657         case FUNCTION:
11658             genFunction (ic);
11659             break;
11660             
11661         case ENDFUNCTION:
11662             genEndFunction (ic);
11663             break;
11664             
11665         case RETURN:
11666             genRet (ic);
11667             break;
11668             
11669         case LABEL:
11670             genLabel (ic);
11671             break;
11672             
11673         case GOTO:
11674             genGoto (ic);
11675             break;
11676             
11677         case '+' :
11678             pic16_genPlus (ic) ;
11679             break;
11680             
11681         case '-' :
11682             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11683                 pic16_genMinus (ic);
11684             break;
11685             
11686         case '*' :
11687             genMult (ic);
11688             break;
11689             
11690         case '/' :
11691             genDiv (ic) ;
11692             break;
11693             
11694         case '%' :
11695             genMod (ic);
11696             break;
11697             
11698         case '>' :
11699             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
11700             break;
11701             
11702         case '<' :
11703             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11704             break;
11705             
11706         case LE_OP:
11707         case GE_OP:
11708         case NE_OP:
11709             
11710             /* note these two are xlated by algebraic equivalence
11711                during parsing SDCC.y */
11712             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11713                    "got '>=' or '<=' shouldn't have come here");
11714             break;      
11715             
11716         case EQ_OP:
11717             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11718             break;          
11719             
11720         case AND_OP:
11721             genAndOp (ic);
11722             break;
11723             
11724         case OR_OP:
11725             genOrOp (ic);
11726             break;
11727             
11728         case '^' :
11729             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11730             break;
11731             
11732         case '|' :
11733                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11734             break;
11735             
11736         case BITWISEAND:
11737             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11738             break;
11739             
11740         case INLINEASM:
11741             genInline (ic);
11742             break;
11743             
11744         case RRC:
11745             genRRC (ic);
11746             break;
11747             
11748         case RLC:
11749             genRLC (ic);
11750             break;
11751             
11752         case GETHBIT:
11753             genGetHbit (ic);
11754             break;
11755             
11756         case LEFT_OP:
11757             genLeftShift (ic);
11758             break;
11759             
11760         case RIGHT_OP:
11761             genRightShift (ic);
11762             break;
11763             
11764         case GET_VALUE_AT_ADDRESS:
11765             genPointerGet(ic);
11766             break;
11767             
11768         case '=' :
11769             if (POINTER_SET(ic))
11770                 genPointerSet(ic);
11771             else
11772                 genAssign(ic);
11773             break;
11774             
11775         case IFX:
11776             genIfx (ic,NULL);
11777             break;
11778             
11779         case ADDRESS_OF:
11780             genAddrOf (ic);
11781             break;
11782             
11783         case JUMPTABLE:
11784             genJumpTab (ic);
11785             break;
11786             
11787         case CAST:
11788             genCast (ic);
11789             break;
11790             
11791         case RECEIVE:
11792             genReceive(ic);
11793             break;
11794             
11795         case SEND:
11796             addSet(&_G.sendSet,ic);
11797             break;
11798
11799         case DUMMY_READ_VOLATILE:
11800           genDummyRead (ic);
11801           break;
11802
11803         default :
11804             ic = ic;
11805         }
11806     }
11807
11808
11809     /* now we are ready to call the
11810        peep hole optimizer */
11811     if (!options.nopeep) {
11812       peepHole (&lineHead);
11813     }
11814     /* now do the actual printing */
11815     printLine (lineHead,codeOutFile);
11816
11817 #ifdef PCODE_DEBUG
11818     DFPRINTF((stderr,"printing pBlock\n\n"));
11819     pic16_printpBlock(stdout,pb);
11820 #endif
11821
11822     return;
11823 }
11824