* src/pic16/device.h (pic16_options): removed field use_crt,
[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 #if 0
877 static int aopIdx (asmop *aop, int offset)
878 {
879   if(!aop)
880     return -1;
881
882   if(aop->type !=  AOP_REG)
883     return -2;
884         
885   return aop->aopu.aop_reg[offset]->rIdx;
886
887 }
888 #endif
889
890 /*-----------------------------------------------------------------*/
891 /* regsInCommon - two operands have some registers in common       */
892 /*-----------------------------------------------------------------*/
893 static bool regsInCommon (operand *op1, operand *op2)
894 {
895     symbol *sym1, *sym2;
896     int i;
897
898     /* if they have registers in common */
899     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
900         return FALSE ;
901
902     sym1 = OP_SYMBOL(op1);
903     sym2 = OP_SYMBOL(op2);
904
905     if (sym1->nRegs == 0 || sym2->nRegs == 0)
906         return FALSE ;
907
908     for (i = 0 ; i < sym1->nRegs ; i++) {
909         int j;
910         if (!sym1->regs[i])
911             continue ;
912
913         for (j = 0 ; j < sym2->nRegs ;j++ ) {
914             if (!sym2->regs[j])
915                 continue ;
916
917             if (sym2->regs[j] == sym1->regs[i])
918                 return TRUE ;
919         }
920     }
921
922     return FALSE ;
923 }
924
925 /*-----------------------------------------------------------------*/
926 /* operandsEqu - equivalent                                        */
927 /*-----------------------------------------------------------------*/
928 static bool operandsEqu ( operand *op1, operand *op2)
929 {
930     symbol *sym1, *sym2;
931
932     /* if they not symbols */
933     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
934         return FALSE;
935
936     sym1 = OP_SYMBOL(op1);
937     sym2 = OP_SYMBOL(op2);
938
939     /* if both are itemps & one is spilt
940        and the other is not then false */
941     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
942         sym1->isspilt != sym2->isspilt )
943         return FALSE ;
944
945     /* if they are the same */
946     if (sym1 == sym2)
947         return TRUE ;
948
949     if (sym1->rname[0] && sym2->rname[0]
950         && strcmp (sym1->rname, sym2->rname) == 0)
951         return TRUE;
952
953
954     /* if left is a tmp & right is not */
955     if (IS_ITEMP(op1)  && 
956         !IS_ITEMP(op2) &&
957         sym1->isspilt  &&
958         (sym1->usl.spillLoc == sym2))
959         return TRUE;
960
961     if (IS_ITEMP(op2)  && 
962         !IS_ITEMP(op1) &&
963         sym2->isspilt  &&
964         sym1->level > 0 &&
965         (sym2->usl.spillLoc == sym1))
966         return TRUE ;
967
968     return FALSE ;
969 }
970
971 /*-----------------------------------------------------------------*/
972 /* pic16_sameRegs - two asmops have the same registers                   */
973 /*-----------------------------------------------------------------*/
974 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
975 {
976     int i;
977
978     if (aop1 == aop2)
979         return TRUE ;
980
981     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
982                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
983
984     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
985
986     if (aop1->type != AOP_REG ||
987         aop2->type != AOP_REG )
988         return FALSE ;
989
990     if (aop1->size != aop2->size )
991         return FALSE ;
992
993     for (i = 0 ; i < aop1->size ; i++ )
994         if (aop1->aopu.aop_reg[i] !=
995             aop2->aopu.aop_reg[i] )
996             return FALSE ;
997
998     return TRUE ;
999 }
1000
1001 /*-----------------------------------------------------------------*/
1002 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1003 /*-----------------------------------------------------------------*/
1004 void pic16_aopOp (operand *op, iCode *ic, bool result)
1005 {
1006     asmop *aop;
1007     symbol *sym;
1008     int i;
1009
1010     if (!op)
1011         return ;
1012
1013 //      DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1014
1015     /* if this a literal */
1016     if (IS_OP_LITERAL(op)) {
1017         op->aop = aop = newAsmop(AOP_LIT);
1018         aop->aopu.aop_lit = op->operand.valOperand;
1019         aop->size = getSize(operandType(op));
1020         return;
1021     }
1022
1023     {
1024       sym_link *type = operandType(op);
1025 #if 0
1026       if(IS_PTR_CONST(type))
1027 #else
1028       if(IS_CODEPTR(type))
1029 #endif
1030         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1031     }
1032
1033     /* if already has a asmop then continue */
1034     if (op->aop)
1035         return ;
1036
1037     /* if the underlying symbol has a aop */
1038     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1039       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1040         op->aop = OP_SYMBOL(op)->aop;
1041         return;
1042     }
1043
1044     /* if this is a true symbol */
1045     if (IS_TRUE_SYMOP(op)) {    
1046         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1047       op->aop = aopForSym(ic, op, result);
1048       return ;
1049     }
1050
1051     /* this is a temporary : this has
1052     only four choices :
1053     a) register
1054     b) spillocation
1055     c) rematerialize 
1056     d) conditional   
1057     e) can be a return use only */
1058
1059     sym = OP_SYMBOL(op);
1060
1061         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
1062     /* if the type is a conditional */
1063     if (sym->regType == REG_CND) {
1064         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1065         aop->size = 0;
1066         return;
1067     }
1068
1069     /* if it is spilt then two situations
1070     a) is rematerialize 
1071     b) has a spill location */
1072     if (sym->isspilt || sym->nRegs == 0) {
1073
1074       DEBUGpic16_emitcode(";","%d",__LINE__);
1075         /* rematerialize it NOW */
1076         if (sym->remat) {
1077
1078             sym->aop = op->aop = aop =
1079                                       aopForRemat (op);
1080             aop->size = getSize(sym->type);
1081             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1082             return;
1083         }
1084
1085 #if 1
1086         if (sym->accuse) {
1087             int i;
1088             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1089             aop->size = getSize(sym->type);
1090             for ( i = 0 ; i < 1 ; i++ ) {
1091                 aop->aopu.aop_str[i] = accUse[i];
1092 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1093             }
1094             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1095             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1096             return;  
1097         }
1098 #endif
1099
1100 #if 1
1101         if (sym->ruonly ) {
1102           /*
1103           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1104           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1105           //pic16_allocDirReg (IC_LEFT(ic));
1106           aop->size = getSize(sym->type);
1107           */
1108
1109           unsigned i;
1110
1111           aop = op->aop = sym->aop = newAsmop(AOP_STR);
1112           aop->size = getSize(sym->type);
1113           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1114             aop->aopu.aop_str[i] = fReturn[i];
1115
1116           DEBUGpic16_emitcode(";","%d",__LINE__);
1117           return;
1118         }
1119 #endif
1120         /* else spill location  */
1121         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1122             /* force a new aop if sizes differ */
1123             sym->usl.spillLoc->aop = NULL;
1124         }
1125         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1126                             __FUNCTION__,__LINE__,
1127                             sym->usl.spillLoc->rname,
1128                             sym->rname, sym->usl.spillLoc->offset);
1129
1130         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1131         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1132         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1133                                           getSize(sym->type), 
1134                                           sym->usl.spillLoc->offset, op);
1135         aop->size = getSize(sym->type);
1136
1137         return;
1138     }
1139
1140     {
1141       sym_link *type = operandType(op);
1142 #if 0
1143       if(IS_PTR_CONST(type)) 
1144 #else
1145       if(IS_CODEPTR(type)) 
1146 #endif
1147         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1148     }
1149
1150     /* must be in a register */
1151     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1152     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1153     aop->size = sym->nRegs;
1154     for ( i = 0 ; i < sym->nRegs ;i++)
1155         aop->aopu.aop_reg[i] = sym->regs[i];
1156 }
1157
1158 /*-----------------------------------------------------------------*/
1159 /* pic16_freeAsmop - free up the asmop given to an operand               */
1160 /*----------------------------------------------------------------*/
1161 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1162 {   
1163     asmop *aop ;
1164
1165     if (!op)
1166         aop = aaop;
1167     else 
1168         aop = op->aop;
1169
1170     if (!aop)
1171         return ;
1172
1173     if (aop->freed)
1174         goto dealloc; 
1175
1176     aop->freed = 1;
1177
1178     /* depending on the asmop type only three cases need work AOP_RO
1179        , AOP_R1 && AOP_STK */
1180 #if 1
1181     switch (aop->type) {
1182         case AOP_FSR0 :
1183             if (_G.fsr0Pushed ) {
1184                 if (pop) {
1185                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1186                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1187 //                    pic16_emitcode ("pop","ar0");
1188                     _G.fsr0Pushed--;
1189                 }
1190             }
1191             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1192             break;
1193
1194         case AOP_FSR2 :
1195             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1196             break;
1197
1198         case AOP_R0 :
1199             if (_G.r0Pushed ) {
1200                 if (pop) {
1201                     pic16_emitcode ("pop","ar0");     
1202                     _G.r0Pushed--;
1203                 }
1204             }
1205             bitVectUnSetBit(ic->rUsed,R0_IDX);
1206             break;
1207
1208         case AOP_R1 :
1209             if (_G.r1Pushed ) {
1210                 if (pop) {
1211                     pic16_emitcode ("pop","ar1");
1212                     _G.r1Pushed--;
1213                 }
1214             }
1215             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1216             break;
1217
1218         case AOP_STK :
1219         {
1220             int sz = aop->size;    
1221             int stk = aop->aopu.aop_stk + aop->size;
1222             bitVectUnSetBit(ic->rUsed,R0_IDX);
1223             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1224
1225             getFreePtr(ic,&aop,FALSE);
1226             
1227             if (options.stack10bit)
1228             {
1229                 /* I'm not sure what to do here yet... */
1230                 /* #STUB */
1231                 fprintf(stderr, 
1232                         "*** Warning: probably generating bad code for "
1233                         "10 bit stack mode.\n");
1234             }
1235             
1236             if (stk) {
1237                 pic16_emitcode ("mov","a,_bp");
1238                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1239                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1240             } else {
1241                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1242             }
1243
1244             while (sz--) {
1245                 pic16_emitcode("pop","acc");
1246                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1247                 if (!sz) break;
1248                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1249             }
1250             op->aop = aop;
1251             pic16_freeAsmop(op,NULL,ic,TRUE);
1252             if (_G.r0Pushed) {
1253                 pic16_emitcode("pop","ar0");
1254                 _G.r0Pushed--;
1255             }
1256
1257             if (_G.r1Pushed) {
1258                 pic16_emitcode("pop","ar1");
1259                 _G.r1Pushed--;
1260             }       
1261         }
1262     }
1263 #endif
1264
1265 dealloc:
1266     /* all other cases just dealloc */
1267     if (op ) {
1268         op->aop = NULL;
1269         if (IS_SYMOP(op)) {
1270             OP_SYMBOL(op)->aop = NULL;    
1271             /* if the symbol has a spill */
1272             if (SPIL_LOC(op))
1273                 SPIL_LOC(op)->aop = NULL;
1274         }
1275     }
1276 }
1277
1278 /*-----------------------------------------------------------------*/
1279 /* pic16_aopGet - for fetching value of the aop                          */
1280 /*-----------------------------------------------------------------*/
1281 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1282 {
1283     char *s = buffer ;
1284     char *rs;
1285
1286     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1287
1288     /* offset is greater than size then zero */
1289     if (offset > (aop->size - 1) &&
1290         aop->type != AOP_LIT)
1291         return zero;
1292
1293     /* depending on type */
1294     switch (aop->type) {
1295
1296     case AOP_FSR0:
1297     case AOP_FSR2:
1298       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1299       rs = Safe_calloc(1, strlen(s)+1);
1300       strcpy(rs, s);
1301       return (rs);
1302       
1303 #if 0
1304       /* if we need to increment it */
1305       while (offset > aop->coff)
1306         {
1307           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1308           aop->coff++;
1309         }
1310
1311       while (offset < aop->coff)
1312         {
1313           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1314           aop->coff--;
1315         }
1316       aop->coff = offset;
1317       if (aop->paged)
1318         {
1319           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1320           return (dname ? "acc" : "a");
1321         }
1322       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1323       rs = Safe_calloc (1, strlen (s) + 1);
1324       strcpy (rs, s);
1325       return rs;
1326 #endif
1327
1328         
1329     case AOP_IMMD:
1330         if (bit16) 
1331             sprintf (s,"%s",aop->aopu.aop_immd);
1332         else
1333             if (offset) 
1334                 sprintf(s,"(%s >> %d)",
1335                         aop->aopu.aop_immd,
1336                         offset*8);
1337             else
1338                 sprintf(s,"%s",
1339                         aop->aopu.aop_immd);
1340         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1341         rs = Safe_calloc(1,strlen(s)+1);
1342         strcpy(rs,s);   
1343         return rs;
1344         
1345     case AOP_DIR:
1346       if (offset) {
1347         sprintf(s,"(%s + %d)",
1348                 aop->aopu.aop_dir,
1349                 offset);
1350         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1351       } else
1352             sprintf(s,"%s",aop->aopu.aop_dir);
1353         rs = Safe_calloc(1,strlen(s)+1);
1354         strcpy(rs,s);   
1355         return rs;
1356         
1357     case AOP_REG:
1358       //if (dname) 
1359       //    return aop->aopu.aop_reg[offset]->dname;
1360       //else
1361             return aop->aopu.aop_reg[offset]->name;
1362         
1363     case AOP_CRY:
1364       //pic16_emitcode(";","%d",__LINE__);
1365       return aop->aopu.aop_dir;
1366         
1367     case AOP_ACC:
1368         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1369 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1370 //        assert( 0 );
1371 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1372         rs = Safe_strdup("WREG");
1373         return (rs);
1374
1375     case AOP_LIT:
1376         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1377         rs = Safe_calloc(1,strlen(s)+1);
1378         strcpy(rs,s);   
1379         return rs;
1380         
1381     case AOP_STR:
1382         aop->coff = offset ;
1383         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1384             dname)
1385             return "acc";
1386         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1387         
1388         return aop->aopu.aop_str[offset];
1389         
1390     case AOP_PCODE:
1391       {
1392         pCodeOp *pcop = aop->aopu.pcop;
1393         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1394         if(pcop->name) {
1395           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1396           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1397           sprintf(s,"%s", pcop->name);
1398         } else
1399           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1400
1401       }
1402       rs = Safe_calloc(1,strlen(s)+1);
1403       strcpy(rs,s);   
1404       return rs;
1405
1406       case AOP_STK:
1407 //        pCodeOp *pcop = aop->aop
1408         break;
1409
1410     }
1411
1412     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1413     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1414            "aopget got unsupported aop->type");
1415     exit(0);
1416 }
1417
1418
1419 /*-----------------------------------------------------------------*/
1420 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1421 /*-----------------------------------------------------------------*/
1422 pCodeOp *pic16_popGetTempReg(void)
1423 {
1424   pCodeOp *pcop;
1425   symbol *cfunc;
1426
1427 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1428
1429         cfunc = currFunc;
1430         currFunc = NULL;
1431
1432         pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1433         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1434                 PCOR(pcop)->r->wasUsed=1;
1435                 PCOR(pcop)->r->isFree=0;
1436
1437                 /* push value on stack */
1438                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1439         }
1440
1441         currFunc = cfunc;
1442
1443   return pcop;
1444 }
1445
1446 /*-----------------------------------------------------------------*/
1447 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1448 /*-----------------------------------------------------------------*/
1449 void pic16_popReleaseTempReg(pCodeOp *pcop)
1450 {
1451         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1452
1453         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1454                 PCOR(pcop)->r->isFree = 1;
1455                 
1456                 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1457         }
1458 }
1459 /*-----------------------------------------------------------------*/
1460 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1461 /*-----------------------------------------------------------------*/
1462 pCodeOp *pic16_popGetLabel(unsigned int key)
1463 {
1464
1465   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1466
1467   if(key>max_key)
1468     max_key = key;
1469
1470   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1471 }
1472
1473 /*-----------------------------------------------------------------*/
1474 /* pic16_popCopyReg - copy a pcode operator                              */
1475 /*-----------------------------------------------------------------*/
1476 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1477 {
1478   pCodeOpReg *pcor;
1479
1480   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1481   pcor->pcop.type = pc->pcop.type;
1482   if(pc->pcop.name) {
1483     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1484       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1485   } else
1486     pcor->pcop.name = NULL;
1487
1488   pcor->r = pc->r;
1489   pcor->rIdx = pc->rIdx;
1490   pcor->r->wasUsed=1;
1491
1492 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1493
1494   return PCOP(pcor);
1495 }
1496
1497 /*-----------------------------------------------------------------*/
1498 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1499 /*-----------------------------------------------------------------*/
1500 pCodeOp *pic16_popGetLit(unsigned int lit)
1501 {
1502   return pic16_newpCodeOpLit(lit);
1503 }
1504
1505 /*-----------------------------------------------------------------*/
1506 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1507 /*-----------------------------------------------------------------*/
1508 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1509 {
1510   return pic16_newpCodeOpLit2(lit, arg2);
1511 }
1512
1513
1514 /*-----------------------------------------------------------------*/
1515 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1516 /*-----------------------------------------------------------------*/
1517 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1518 {
1519   return pic16_newpCodeOpImmd(name, offset,index, 0);
1520 }
1521
1522
1523 /*-----------------------------------------------------------------*/
1524 /* pic16_popGet - asm operator to pcode operator conversion              */
1525 /*-----------------------------------------------------------------*/
1526 pCodeOp *pic16_popGetWithString(char *str)
1527 {
1528   pCodeOp *pcop;
1529
1530
1531   if(!str) {
1532     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1533     exit (1);
1534   }
1535
1536   pcop = pic16_newpCodeOp(str,PO_STR);
1537
1538   return pcop;
1539 }
1540
1541 /*-----------------------------------------------------------------*/
1542 /* pic16_popRegFromString -                                        */
1543 /*-----------------------------------------------------------------*/
1544 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1545 {
1546
1547   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1548   pcop->type = PO_DIR;
1549
1550   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1551   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1552
1553   if(!str)
1554     str = "BAD_STRING";
1555
1556   pcop->name = Safe_calloc(1,strlen(str)+1);
1557   strcpy(pcop->name,str);
1558
1559   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1560
1561   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1562   if(PCOR(pcop)->r == NULL) {
1563 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1564 //              __FUNCTION__, __LINE__, str, size, offset);
1565
1566
1567 //    PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1568         fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1569
1570 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1571   } else {
1572 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d",__LINE__,pcop->name,size,offset);
1573   }
1574   PCOR(pcop)->instance = offset;
1575
1576   return pcop;
1577 }
1578
1579 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1580 {
1581   pCodeOp *pcop;
1582
1583 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1584
1585         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1586         PCOR(pcop)->rIdx = rIdx;
1587         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1588
1589         PCOR(pcop)->r->isFree = 0;
1590         PCOR(pcop)->r->wasUsed = 1;
1591
1592         pcop->type = PCOR(pcop)->r->pc_type;
1593
1594   return pcop;
1595 }
1596
1597 /*---------------------------------------------------------------------------------*/
1598 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1599 /*                 VR 030601                                                       */
1600 /*---------------------------------------------------------------------------------*/
1601 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1602 {
1603   pCodeOpReg2 *pcop2;
1604   pCodeOp *temp;
1605   
1606         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1607
1608         /* comment the following check, so errors to throw up */
1609 //      if(!pcop2)return NULL;
1610
1611         temp = pic16_popGet(aop_dst, offset);
1612         pcop2->pcop2 = temp;
1613         
1614   return PCOP(pcop2);
1615 }
1616
1617
1618
1619 /*--------------------------------------------------------------------------------.-*/
1620 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1621 /*                  VR 030601 , adapted by Hans Dorn                                */
1622 /*--------------------------------------------------------------------------------.-*/
1623 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1624 {
1625   pCodeOpReg2 *pcop2;
1626  
1627         pcop2 = (pCodeOpReg2 *)src;
1628         pcop2->pcop2 = dst;
1629         
1630         return PCOP(pcop2);
1631 }
1632
1633
1634
1635 /*---------------------------------------------------------------------------------*/
1636 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1637 /*                     movff instruction                                           */
1638 /*---------------------------------------------------------------------------------*/
1639 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1640 {
1641   pCodeOpReg2 *pcop2;
1642
1643         if(!noalloc) {
1644                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1645                 pcop2->pcop2 = pic16_popCopyReg(dst);
1646         } else {
1647                 /* the pCodeOp may be already allocated */
1648                 pcop2 = (pCodeOpReg2 *)(src);
1649                 pcop2->pcop2 = (pCodeOp *)(dst);
1650         }
1651
1652   return PCOP(pcop2);
1653 }
1654
1655
1656 /*-----------------------------------------------------------------*/
1657 /* pic16_popGet - asm operator to pcode operator conversion              */
1658 /*-----------------------------------------------------------------*/
1659 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1660 {
1661   //char *s = buffer ;
1662   char *rs;
1663   pCodeOp *pcop;
1664
1665     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1666     /* offset is greater than
1667     size then zero */
1668
1669 //    if (offset > (aop->size - 1) &&
1670 //        aop->type != AOP_LIT)
1671 //      return NULL;  //zero;
1672
1673     /* depending on type */
1674     switch (aop->type) {
1675         
1676     case AOP_R0:
1677     case AOP_R1:
1678     case AOP_DPTR:
1679     case AOP_DPTR2:
1680         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1681         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1682         assert( 0 );
1683         return NULL;
1684
1685
1686     case AOP_FSR0:
1687     case AOP_FSR2:
1688       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1689       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
1690       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1691       PCOR(pcop)->r->wasUsed = 1;
1692       PCOR(pcop)->r->isFree = 0;
1693       
1694       PCOR(pcop)->instance = offset;
1695       pcop->type = PCOR(pcop)->r->pc_type;
1696       return (pcop);
1697
1698     case AOP_IMMD:
1699       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1700       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1701
1702     case AOP_ACC:
1703       {
1704         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1705
1706         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1707
1708         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1709         
1710         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1711         PCOR(pcop)->rIdx = rIdx;
1712         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1713         PCOR(pcop)->r->wasUsed=1;
1714         PCOR(pcop)->r->isFree=0;
1715
1716         PCOR(pcop)->instance = offset;
1717         pcop->type = PCOR(pcop)->r->pc_type;
1718 //      rs = aop->aopu.aop_reg[offset]->name;
1719 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1720         return pcop;
1721
1722
1723 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1724 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1725
1726 //      assert( 0 );
1727       }
1728         
1729     case AOP_DIR:
1730       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1731       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1732         
1733     case AOP_REG:
1734       {
1735         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1736
1737         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1738         
1739         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1740 //      pcop->type = PO_GPR_REGISTER;
1741         PCOR(pcop)->rIdx = rIdx;
1742         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
1743         PCOR(pcop)->r->wasUsed=1;
1744         PCOR(pcop)->r->isFree=0;
1745
1746         PCOR(pcop)->instance = offset;
1747         pcop->type = PCOR(pcop)->r->pc_type;
1748         rs = aop->aopu.aop_reg[offset]->name;
1749         DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1750         return pcop;
1751       }
1752
1753     case AOP_CRY:
1754         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1755
1756       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1757       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1758       //if(PCOR(pcop)->r == NULL)
1759       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1760       return pcop;
1761         
1762     case AOP_LIT:
1763         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1764       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1765
1766     case AOP_STR:
1767       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1768       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1769
1770       /*
1771       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1772       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1773       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1774       pcop->type = PCOR(pcop)->r->pc_type;
1775       pcop->name = PCOR(pcop)->r->name;
1776
1777       return pcop;
1778       */
1779
1780     case AOP_PCODE:
1781       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1782                           __LINE__, 
1783                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1784       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1785 #if 1
1786         switch( aop->aopu.pcop->type ) {
1787                 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1788                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1789                 default:
1790                         assert( 0 );    /* should never reach here */;
1791         }
1792 #else
1793       PCOI(pcop)->offset = offset;
1794 #endif
1795       return pcop;
1796     }
1797
1798     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1799            "pic16_popGet got unsupported aop->type");
1800     exit(0);
1801 }
1802 /*-----------------------------------------------------------------*/
1803 /* pic16_aopPut - puts a string for a aop                                */
1804 /*-----------------------------------------------------------------*/
1805 void pic16_aopPut (asmop *aop, char *s, int offset)
1806 {
1807     char *d = buffer ;
1808     symbol *lbl ;
1809
1810     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1811
1812     if (aop->size && offset > ( aop->size - 1)) {
1813         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1814                "pic16_aopPut got offset > aop->size");
1815         exit(0);
1816     }
1817
1818     /* will assign value to value */
1819     /* depending on where it is ofcourse */
1820     switch (aop->type) {
1821     case AOP_DIR:
1822       if (offset) {
1823         sprintf(d,"(%s + %d)",
1824                 aop->aopu.aop_dir,offset);
1825         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1826
1827       } else
1828             sprintf(d,"%s",aop->aopu.aop_dir);
1829         
1830         if (strcmp(d,s)) {
1831           DEBUGpic16_emitcode(";","%d",__LINE__);
1832           if(strcmp(s,"W"))
1833             pic16_emitcode("movf","%s,w",s);
1834           pic16_emitcode("movwf","%s",d);
1835
1836           if(strcmp(s,"W")) {
1837             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1838             if(offset >= aop->size) {
1839               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1840               break;
1841             } else
1842               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1843           }
1844
1845           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1846
1847
1848         }
1849         break;
1850         
1851     case AOP_REG:
1852       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1853         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1854           /*
1855             if (*s == '@'           ||
1856                 strcmp(s,"r0") == 0 ||
1857                 strcmp(s,"r1") == 0 ||
1858                 strcmp(s,"r2") == 0 ||
1859                 strcmp(s,"r3") == 0 ||
1860                 strcmp(s,"r4") == 0 ||
1861                 strcmp(s,"r5") == 0 ||
1862                 strcmp(s,"r6") == 0 || 
1863                 strcmp(s,"r7") == 0 )
1864                 pic16_emitcode("mov","%s,%s  ; %d",
1865                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1866             else
1867           */
1868
1869           if(strcmp(s,"W")==0 )
1870             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1871
1872           pic16_emitcode("movwf","%s",
1873                    aop->aopu.aop_reg[offset]->name);
1874
1875           if(strcmp(s,zero)==0) {
1876             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1877
1878           } else if(strcmp(s,"W")==0) {
1879             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1880             pcop->type = PO_GPR_REGISTER;
1881
1882             PCOR(pcop)->rIdx = -1;
1883             PCOR(pcop)->r = NULL;
1884
1885             DEBUGpic16_emitcode(";","%d",__LINE__);
1886             pcop->name = Safe_strdup(s);
1887             pic16_emitpcode(POC_MOVFW,pcop);
1888             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1889           } else if(strcmp(s,one)==0) {
1890             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1891             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1892           } else {
1893             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1894           }
1895         }
1896         break;
1897         
1898     case AOP_DPTR:
1899     case AOP_DPTR2:
1900     
1901     if (aop->type == AOP_DPTR2)
1902     {
1903         genSetDPTR(1);
1904     }
1905     
1906         if (aop->code) {
1907             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1908                    "pic16_aopPut writting to code space");
1909             exit(0);
1910         }
1911         
1912         while (offset > aop->coff) {
1913             aop->coff++;
1914             pic16_emitcode ("inc","dptr");
1915         }
1916         
1917         while (offset < aop->coff) {
1918             aop->coff-- ;
1919             pic16_emitcode("lcall","__decdptr");
1920         }
1921         
1922         aop->coff = offset;
1923         
1924         /* if not in accumulater */
1925         MOVA(s);        
1926         
1927         pic16_emitcode ("movx","@dptr,a");
1928         
1929     if (aop->type == AOP_DPTR2)
1930     {
1931         genSetDPTR(0);
1932     }
1933         break;
1934         
1935     case AOP_R0:
1936     case AOP_R1:
1937         while (offset > aop->coff) {
1938             aop->coff++;
1939             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1940         }
1941         while (offset < aop->coff) {
1942             aop->coff-- ;
1943             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1944         }
1945         aop->coff = offset;
1946         
1947         if (aop->paged) {
1948             MOVA(s);           
1949             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1950             
1951         } else
1952             if (*s == '@') {
1953                 MOVA(s);
1954                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1955             } else
1956                 if (strcmp(s,"r0") == 0 ||
1957                     strcmp(s,"r1") == 0 ||
1958                     strcmp(s,"r2") == 0 ||
1959                     strcmp(s,"r3") == 0 ||
1960                     strcmp(s,"r4") == 0 ||
1961                     strcmp(s,"r5") == 0 ||
1962                     strcmp(s,"r6") == 0 || 
1963                     strcmp(s,"r7") == 0 ) {
1964                     char buffer[10];
1965                     sprintf(buffer,"a%s",s);
1966                     pic16_emitcode("mov","@%s,%s",
1967                              aop->aopu.aop_ptr->name,buffer);
1968                 } else
1969                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1970         
1971         break;
1972         
1973     case AOP_STK:
1974         if (strcmp(s,"a") == 0)
1975             pic16_emitcode("push","acc");
1976         else
1977             pic16_emitcode("push","%s",s);
1978         
1979         break;
1980         
1981     case AOP_CRY:
1982         /* if bit variable */
1983         if (!aop->aopu.aop_dir) {
1984             pic16_emitcode("clr","a");
1985             pic16_emitcode("rlc","a");
1986         } else {
1987             if (s == zero) 
1988                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1989             else
1990                 if (s == one)
1991                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1992                 else
1993                     if (!strcmp(s,"c"))
1994                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1995                     else {
1996                         lbl = newiTempLabel(NULL);
1997                         
1998                         if (strcmp(s,"a")) {
1999                             MOVA(s);
2000                         }
2001                         pic16_emitcode("clr","c");
2002                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2003                         pic16_emitcode("cpl","c");
2004                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2005                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2006                     }
2007         }
2008         break;
2009         
2010     case AOP_STR:
2011         aop->coff = offset;
2012         if (strcmp(aop->aopu.aop_str[offset],s))
2013             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2014         break;
2015         
2016     case AOP_ACC:
2017         aop->coff = offset;
2018         if (!offset && (strcmp(s,"acc") == 0))
2019             break;
2020         
2021         if (strcmp(aop->aopu.aop_str[offset],s))
2022             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2023         break;
2024
2025     default :
2026         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2027                "pic16_aopPut got unsupported aop->type");
2028         exit(0);    
2029     }    
2030
2031 }
2032
2033 /*-----------------------------------------------------------------*/
2034 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
2035 /*-----------------------------------------------------------------*/
2036 static void mov2w (asmop *aop, int offset)
2037 {
2038
2039 //  if(!aop)
2040 //    return;
2041
2042         DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2043
2044         if(is_LitAOp(aop))
2045                 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2046         else
2047                 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2048
2049 }
2050
2051
2052 /* push pcop into stack */
2053 void pic16_pushpCodeOp(pCodeOp *pcop)
2054 {
2055 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2056         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
2057 }
2058
2059 /* pop pcop from stack */
2060 void pic16_poppCodeOp(pCodeOp *pcop)
2061 {
2062         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
2063 }
2064
2065
2066 /*-----------------------------------------------------------------*/
2067 /* pushw - pushes wreg to stack                                    */
2068 /*-----------------------------------------------------------------*/
2069 void pushw(void)
2070 {
2071         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2072         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2073 }
2074
2075                 
2076 /*-----------------------------------------------------------------*/
2077 /* pushaop - pushes aop to stack                                   */
2078 /*-----------------------------------------------------------------*/
2079 void pushaop(asmop *aop, int offset)
2080 {
2081         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2082         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
2083 }
2084
2085 /*-----------------------------------------------------------------*/
2086 /* popaop - pops aop from stack                                    */
2087 /*-----------------------------------------------------------------*/
2088 void popaop(asmop *aop, int offset)
2089 {
2090         DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2091         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
2092 }
2093
2094 void popaopidx(asmop *aop, int offset, int index)
2095 {
2096   int ofs=1;
2097
2098         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2099
2100         if(STACK_MODEL_LARGE)ofs++;
2101
2102         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2103         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
2104 }
2105
2106 /*-----------------------------------------------------------------*/
2107 /* reAdjustPreg - points a register back to where it should        */
2108 /*-----------------------------------------------------------------*/
2109 static void reAdjustPreg (asmop *aop)
2110 {
2111     int size ;
2112
2113     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2114     aop->coff = 0;
2115     if ((size = aop->size) <= 1)
2116         return ;
2117     size-- ;
2118     switch (aop->type) {
2119         case AOP_R0 :
2120         case AOP_R1 :
2121             while (size--)
2122                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2123             break;          
2124         case AOP_DPTR :
2125         case AOP_DPTR2:
2126             if (aop->type == AOP_DPTR2)
2127             {
2128                 genSetDPTR(1);
2129             } 
2130             while (size--)
2131             {
2132                 pic16_emitcode("lcall","__decdptr");
2133             }
2134                 
2135             if (aop->type == AOP_DPTR2)
2136             {
2137                 genSetDPTR(0);
2138             }                
2139             break;  
2140
2141     }   
2142
2143 }
2144
2145
2146 #if 0
2147 /*-----------------------------------------------------------------*/
2148 /* opIsGptr: returns non-zero if the passed operand is             */   
2149 /* a generic pointer type.                                         */
2150 /*-----------------------------------------------------------------*/ 
2151 static int opIsGptr(operand *op)
2152 {
2153     sym_link *type = operandType(op);
2154     
2155     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2156     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2157     {
2158         return 1;
2159     }
2160     return 0;        
2161 }
2162 #endif
2163
2164 /*-----------------------------------------------------------------*/
2165 /* pic16_getDataSize - get the operand data size                         */
2166 /*-----------------------------------------------------------------*/
2167 int pic16_getDataSize(operand *op)
2168 {
2169     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2170
2171
2172     return AOP_SIZE(op);
2173
2174     // tsd- in the pic port, the genptr size is 1, so this code here
2175     // fails. ( in the 8051 port, the size was 4).
2176 #if 0
2177     int size;
2178     size = AOP_SIZE(op);
2179     if (size == GPTRSIZE)
2180     {
2181         sym_link *type = operandType(op);
2182         if (IS_GENPTR(type))
2183         {
2184             /* generic pointer; arithmetic operations
2185              * should ignore the high byte (pointer type).
2186              */
2187             size--;
2188     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2189         }
2190     }
2191     return size;
2192 #endif
2193 }
2194
2195 /*-----------------------------------------------------------------*/
2196 /* pic16_outAcc - output Acc                                             */
2197 /*-----------------------------------------------------------------*/
2198 void pic16_outAcc(operand *result)
2199 {
2200   int size,offset;
2201   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2202   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2203
2204
2205   size = pic16_getDataSize(result);
2206   if(size){
2207     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2208     size--;
2209     offset = 1;
2210     /* unsigned or positive */
2211     while(size--)
2212       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2213   }
2214
2215 }
2216
2217 /*-----------------------------------------------------------------*/
2218 /* pic16_outBitC - output a bit C                                  */
2219 /*                 Move to result the value of Carry flag -- VR    */
2220 /*-----------------------------------------------------------------*/
2221 void pic16_outBitC(operand *result)
2222 {
2223   int i;
2224
2225     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2226     /* if the result is bit */
2227     if (AOP_TYPE(result) == AOP_CRY) {
2228         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2229         pic16_aopPut(AOP(result),"c",0);
2230     } else {
2231
2232         i = AOP_SIZE(result);
2233         while(i--) {
2234                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2235         }
2236         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2237         
2238 /*
2239         pic16_emitcode("clr","a  ; %d", __LINE__);
2240         pic16_emitcode("rlc","a");
2241         pic16_outAcc(result);
2242 */
2243     }
2244 }
2245
2246 /*-----------------------------------------------------------------*/
2247 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2248 /*-----------------------------------------------------------------*/
2249 void pic16_toBoolean(operand *oper)
2250 {
2251     int size = AOP_SIZE(oper) - 1;
2252     int offset = 1;
2253
2254     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2255
2256     if ( AOP_TYPE(oper) != AOP_ACC) {
2257       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2258     }
2259     while (size--) {
2260       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2261     }
2262 }
2263
2264
2265 #if !defined(GEN_Not)
2266 /*-----------------------------------------------------------------*/
2267 /* genNot - generate code for ! operation                          */
2268 /*-----------------------------------------------------------------*/
2269 static void pic16_genNot (iCode *ic)
2270 {
2271   symbol *tlbl;
2272   int size;
2273
2274   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2275   /* assign asmOps to operand & result */
2276   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2277   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2278
2279   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2280   /* if in bit space then a special case */
2281   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2282     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2283       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2284       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2285     } else {
2286       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2287       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2288       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2289     }
2290     goto release;
2291   }
2292
2293   size = AOP_SIZE(IC_LEFT(ic));
2294   if(size == 1) {
2295     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2296     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2297     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2298     goto release;
2299   }
2300   pic16_toBoolean(IC_LEFT(ic));
2301
2302   tlbl = newiTempLabel(NULL);
2303   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2304   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2305   pic16_outBitC(IC_RESULT(ic));
2306
2307  release:    
2308   /* release the aops */
2309   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2310   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2311 }
2312 #endif
2313
2314
2315 #if !defined(GEN_Cpl)
2316 /*-----------------------------------------------------------------*/
2317 /* genCpl - generate code for complement                           */
2318 /*-----------------------------------------------------------------*/
2319 static void pic16_genCpl (iCode *ic)
2320 {
2321     int offset = 0;
2322     int size ;
2323
2324
2325     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2326     /* assign asmOps to operand & result */
2327     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2328     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2329
2330     /* if both are in bit space then 
2331     a special case */
2332     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2333         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2334
2335         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2336         pic16_emitcode("cpl","c"); 
2337         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2338         goto release; 
2339     } 
2340
2341     size = AOP_SIZE(IC_RESULT(ic));
2342     while (size--) {
2343 /*
2344         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2345         MOVA(l);       
2346         pic16_emitcode("cpl","a");
2347         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2348 */
2349         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2350               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2351         } else {
2352                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2353                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2354         }
2355         offset++;
2356
2357     }
2358
2359
2360 release:
2361     /* release the aops */
2362     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2363     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2364 }
2365 #endif
2366
2367 /*-----------------------------------------------------------------*/
2368 /* genUminusFloat - unary minus for floating points                */
2369 /*-----------------------------------------------------------------*/
2370 static void genUminusFloat(operand *op,operand *result)
2371 {
2372     int size ,offset =0 ;
2373     char *l;
2374
2375     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2376     /* for this we just need to flip the 
2377     first it then copy the rest in place */
2378     size = AOP_SIZE(op) - 1;
2379     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2380
2381     MOVA(l);    
2382
2383     pic16_emitcode("cpl","acc.7");
2384     pic16_aopPut(AOP(result),"a",3);    
2385
2386     while(size--) {
2387         pic16_aopPut(AOP(result),
2388                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2389                offset);
2390         offset++;
2391     }          
2392 }
2393
2394 /*-----------------------------------------------------------------*/
2395 /* genUminus - unary minus code generation                         */
2396 /*-----------------------------------------------------------------*/
2397 static void genUminus (iCode *ic)
2398 {
2399   int size, i;
2400   sym_link *optype, *rtype;
2401
2402         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2403         
2404         /* assign asmops */
2405         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2406         pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2407
2408         /* if both in bit space then special case */
2409         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2410                 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2411
2412                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2413                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2414                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2415                 
2416                 goto release; 
2417         } 
2418
2419         optype = operandType(IC_LEFT(ic));
2420         rtype = operandType(IC_RESULT(ic));
2421
2422         /* if float then do float stuff */
2423         if (IS_FLOAT(optype)) {
2424                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2425                 goto release;
2426         }
2427
2428         /* otherwise subtract from zero by taking the 2's complement */
2429         size = AOP_SIZE(IC_LEFT(ic));
2430
2431         for(i=0; i<size; i++) {
2432                 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2433                         pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2434                 else {
2435                         pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2436                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2437                 }
2438         }
2439
2440         pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2441         for(i=1; i<size; i++) {
2442                 emitSKPNZ;
2443                 pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2444         }
2445
2446 release:
2447         /* release the aops */
2448         pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2449         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2450 }
2451
2452 /*-----------------------------------------------------------------*/
2453 /* saveRegisters - will look for a call and save the registers     */
2454 /*-----------------------------------------------------------------*/
2455 static void saveRegisters(iCode *lic) 
2456 {
2457     int i;
2458     iCode *ic;
2459     bitVect *rsave;
2460     sym_link *dtype;
2461
2462     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2463     /* look for call */
2464     for (ic = lic ; ic ; ic = ic->next) 
2465         if (ic->op == CALL || ic->op == PCALL)
2466             break;
2467
2468     if (!ic) {
2469         fprintf(stderr,"found parameter push with no function call\n");
2470         return ;
2471     }
2472
2473     /* if the registers have been saved already then
2474     do nothing */
2475     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2476         return ;
2477
2478     /* find the registers in use at this time 
2479     and push them away to safety */
2480     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2481                           ic->rUsed);
2482
2483     ic->regsSaved = 1;
2484     if (options.useXstack) {
2485         if (bitVectBitValue(rsave,R0_IDX))
2486             pic16_emitcode("mov","b,r0");
2487         pic16_emitcode("mov","r0,%s",spname);
2488         for (i = 0 ; i < pic16_nRegs ; i++) {
2489             if (bitVectBitValue(rsave,i)) {
2490                 if (i == R0_IDX)
2491                     pic16_emitcode("mov","a,b");
2492                 else
2493                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2494                 pic16_emitcode("movx","@r0,a");
2495                 pic16_emitcode("inc","r0");
2496             }
2497         }
2498         pic16_emitcode("mov","%s,r0",spname);
2499         if (bitVectBitValue(rsave,R0_IDX))
2500             pic16_emitcode("mov","r0,b");           
2501     }// else
2502     //for (i = 0 ; i < pic16_nRegs ; i++) {
2503     //    if (bitVectBitValue(rsave,i))
2504     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2505     //}
2506
2507     dtype = operandType(IC_LEFT(ic));
2508     if (currFunc && dtype && 
2509         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2510         IFFUNC_ISISR(currFunc->type) &&
2511         !ic->bankSaved) 
2512
2513         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2514
2515 }
2516 /*-----------------------------------------------------------------*/
2517 /* unsaveRegisters - pop the pushed registers                      */
2518 /*-----------------------------------------------------------------*/
2519 static void unsaveRegisters (iCode *ic)
2520 {
2521     int i;
2522     bitVect *rsave;
2523
2524     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2525     /* find the registers in use at this time 
2526     and push them away to safety */
2527     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2528                           ic->rUsed);
2529     
2530     if (options.useXstack) {
2531         pic16_emitcode("mov","r0,%s",spname);   
2532         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2533             if (bitVectBitValue(rsave,i)) {
2534                 pic16_emitcode("dec","r0");
2535                 pic16_emitcode("movx","a,@r0");
2536                 if (i == R0_IDX)
2537                     pic16_emitcode("mov","b,a");
2538                 else
2539                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2540             }       
2541
2542         }
2543         pic16_emitcode("mov","%s,r0",spname);
2544         if (bitVectBitValue(rsave,R0_IDX))
2545             pic16_emitcode("mov","r0,b");
2546     } //else
2547     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2548     //    if (bitVectBitValue(rsave,i))
2549     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2550     //}
2551
2552 }  
2553
2554 #if 0  // patch 14
2555 /*-----------------------------------------------------------------*/
2556 /* pushSide -                                                      */
2557 /*-----------------------------------------------------------------*/
2558 static void pushSide(operand * oper, int size)
2559 {
2560         int offset = 0;
2561     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2562         while (size--) {
2563                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2564                 if (AOP_TYPE(oper) != AOP_REG &&
2565                     AOP_TYPE(oper) != AOP_DIR &&
2566                     strcmp(l,"a") ) {
2567                         pic16_emitcode("mov","a,%s",l);
2568                         pic16_emitcode("push","acc");
2569                 } else
2570                         pic16_emitcode("push","%s",l);
2571         }
2572 }
2573 #endif // patch 14
2574
2575 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2576 {
2577 //              (AOP(left)->aopu.pcop->type == PO_DIR)?
2578
2579         if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2580                 pic16_emitpcode(POC_MOVFW, src);
2581                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2582         } else {
2583                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2584                         src, pic16_popGet(AOP(op), offset)));
2585         }
2586 }
2587
2588
2589 /*-----------------------------------------------------------------*/
2590 /* assignResultValue - assign results to oper, rescall==1 is       */
2591 /*                     called from genCall() or genPCall()         */
2592 /*-----------------------------------------------------------------*/
2593 static void assignResultValue(operand * oper, int rescall)
2594 {
2595   int size = AOP_SIZE(oper);
2596
2597         DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2598         DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2599
2600         if(rescall) {
2601                 /* assign result from a call/pcall function() */
2602                 
2603                 /* function results are stored in a special order,
2604                  * see top of file with Function return policy, or manual */
2605
2606                 if(size <= 4) {
2607                         /* 8-bits, result in WREG */
2608                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2609                         
2610                         if(size>1) {
2611                                 /* 16-bits, result in PRODL:WREG */
2612                                 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2613                         }
2614                         
2615                         if(size>2) {
2616                                 /* 24-bits, result in PRODH:PRODL:WREG */
2617                                 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2618                         }
2619                         
2620                         if(size>3) {
2621                                 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2622                                 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2623                         }
2624                 } else {
2625                         /* >32-bits, result on stack, and FSR0 points to beginning.
2626                          * Fix stack when done */
2627                          /* FIXME FIXME */
2628                         while (size--) {
2629 //                              DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2630 //                              DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2631                 
2632                                 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2633                                 GpsuedoStkPtr++;
2634                         }
2635                         
2636                         /* fix stack */
2637                         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2638                         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2639                         if(STACK_MODEL_LARGE) {
2640                                 emitSKPNC;
2641                                 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2642                         }
2643                 }                       
2644         } else {        
2645                 if(!GpsuedoStkPtr) {
2646 //                      DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2647                         /* The last byte in the assignment is in W */
2648                         size--;
2649                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2650                         GpsuedoStkPtr++;
2651                 }
2652
2653                 while (size--) {
2654 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2655 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2656                 
2657                         popaopidx(AOP(oper), size, GpsuedoStkPtr);
2658                         GpsuedoStkPtr++;
2659
2660 #if 0
2661 #if STACK_SUPPORT
2662                 if(!USE_STACK)
2663                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2664 #else
2665                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2666 #endif
2667 #endif
2668
2669                 }
2670         }
2671                 
2672 }
2673
2674
2675 /*-----------------------------------------------------------------*/
2676 /* genIpush - genrate code for pushing this gets a little complex  */
2677 /*-----------------------------------------------------------------*/
2678 static void genIpush (iCode *ic)
2679 {
2680   int size, offset=0;
2681
2682   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2683
2684
2685         pic16_aopOp(IC_LEFT(ic), ic, FALSE);
2686         
2687
2688         size = AOP_SIZE( IC_LEFT(ic) );
2689         
2690         while(size--) {
2691                 mov2w( AOP(IC_LEFT(ic)), offset );
2692                 pushw();
2693                 offset++;
2694         }
2695         
2696 #if 0
2697     int size, offset = 0 ;
2698     char *l;
2699
2700
2701     /* if this is not a parm push : ie. it is spill push 
2702     and spill push is always done on the local stack */
2703     if (!ic->parmPush) {
2704
2705         /* and the item is spilt then do nothing */
2706         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2707             return ;
2708
2709         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2710         size = AOP_SIZE(IC_LEFT(ic));
2711         /* push it on the stack */
2712         while(size--) {
2713             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2714             if (*l == '#') {
2715                 MOVA(l);
2716                 l = "acc";
2717             }
2718             pic16_emitcode("push","%s",l);
2719         }
2720         return ;        
2721     }
2722
2723     /* this is a paramter push: in this case we call
2724     the routine to find the call and save those
2725     registers that need to be saved */   
2726     saveRegisters(ic);
2727
2728     /* then do the push */
2729     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2730
2731
2732         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2733     size = AOP_SIZE(IC_LEFT(ic));
2734
2735     while (size--) {
2736         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2737         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2738             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2739             strcmp(l,"a") ) {
2740             pic16_emitcode("mov","a,%s",l);
2741             pic16_emitcode("push","acc");
2742         } else
2743             pic16_emitcode("push","%s",l);
2744     }       
2745
2746     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2747 #endif
2748 }
2749
2750 /*-----------------------------------------------------------------*/
2751 /* genIpop - recover the registers: can happen only for spilling   */
2752 /*-----------------------------------------------------------------*/
2753 static void genIpop (iCode *ic)
2754 {
2755   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2756 #if 0
2757     int size,offset ;
2758
2759
2760     /* if the temp was not pushed then */
2761     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2762         return ;
2763
2764     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2765     size = AOP_SIZE(IC_LEFT(ic));
2766     offset = (size-1);
2767     while (size--) 
2768         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2769                                    FALSE,TRUE));
2770
2771     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2772 #endif
2773 }
2774
2775 /*-----------------------------------------------------------------*/
2776 /* unsaverbank - restores the resgister bank from stack            */
2777 /*-----------------------------------------------------------------*/
2778 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2779 {
2780   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2781 #if 0
2782     int i;
2783     asmop *aop ;
2784     regs *r = NULL;
2785
2786     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2787     if (popPsw) {
2788         if (options.useXstack) {
2789             aop = newAsmop(0);
2790             r = getFreePtr(ic,&aop,FALSE);
2791             
2792             
2793             pic16_emitcode("mov","%s,_spx",r->name);
2794             pic16_emitcode("movx","a,@%s",r->name);
2795             pic16_emitcode("mov","psw,a");
2796             pic16_emitcode("dec","%s",r->name);
2797             
2798         }else
2799             pic16_emitcode ("pop","psw");
2800     }
2801
2802     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2803         if (options.useXstack) {       
2804             pic16_emitcode("movx","a,@%s",r->name);
2805             //pic16_emitcode("mov","(%s+%d),a",
2806             //       regspic16[i].base,8*bank+regspic16[i].offset);
2807             pic16_emitcode("dec","%s",r->name);
2808
2809         } else 
2810           pic16_emitcode("pop",""); //"(%s+%d)",
2811         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2812     }
2813
2814     if (options.useXstack) {
2815
2816         pic16_emitcode("mov","_spx,%s",r->name);
2817         pic16_freeAsmop(NULL,aop,ic,TRUE);
2818
2819     }
2820 #endif 
2821 }
2822
2823 /*-----------------------------------------------------------------*/
2824 /* saverbank - saves an entire register bank on the stack          */
2825 /*-----------------------------------------------------------------*/
2826 static void saverbank (int bank, iCode *ic, bool pushPsw)
2827 {
2828   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2829 #if 0
2830     int i;
2831     asmop *aop ;
2832     regs *r = NULL;
2833
2834     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2835     if (options.useXstack) {
2836
2837         aop = newAsmop(0);
2838         r = getFreePtr(ic,&aop,FALSE);  
2839         pic16_emitcode("mov","%s,_spx",r->name);
2840
2841     }
2842
2843     for (i = 0 ; i < pic16_nRegs ;i++) {
2844         if (options.useXstack) {
2845             pic16_emitcode("inc","%s",r->name);
2846             //pic16_emitcode("mov","a,(%s+%d)",
2847             //         regspic16[i].base,8*bank+regspic16[i].offset);
2848             pic16_emitcode("movx","@%s,a",r->name);           
2849         } else 
2850           pic16_emitcode("push","");// "(%s+%d)",
2851                      //regspic16[i].base,8*bank+regspic16[i].offset);
2852     }
2853     
2854     if (pushPsw) {
2855         if (options.useXstack) {
2856             pic16_emitcode("mov","a,psw");
2857             pic16_emitcode("movx","@%s,a",r->name);     
2858             pic16_emitcode("inc","%s",r->name);
2859             pic16_emitcode("mov","_spx,%s",r->name);       
2860             pic16_freeAsmop (NULL,aop,ic,TRUE);
2861             
2862         } else
2863             pic16_emitcode("push","psw");
2864         
2865         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2866     }
2867     ic->bankSaved = 1;
2868 #endif
2869 }
2870
2871
2872
2873 /*-----------------------------------------------------------------*/
2874 /* genCall - generates a call statement                            */
2875 /*-----------------------------------------------------------------*/
2876 static void genCall (iCode *ic)
2877 {
2878   sym_link *dtype;   
2879   int stackParms=0;
2880   
2881         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2882
2883         /* if caller saves & we have not saved then */
2884         if (!ic->regsSaved)
2885                 saveRegisters(ic);
2886
2887         /* if we are calling a function that is not using
2888          * the same register bank then we need to save the
2889          * destination registers on the stack */
2890         dtype = operandType(IC_LEFT(ic));
2891         if (currFunc && dtype && 
2892                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2893                 IFFUNC_ISISR(currFunc->type) &&
2894                 !ic->bankSaved) 
2895
2896                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2897
2898
2899         /* initialise stackParms for IPUSH pushes */
2900 //      stackParms = psuedoStkPtr;
2901 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
2902
2903         /* if send set is not empty the assign */
2904         if (_G.sendSet) {
2905           iCode *sic;
2906
2907                 /* For the Pic port, there is no data stack.
2908                  * So parameters passed to functions are stored
2909                  * in registers. (The pCode optimizer will get
2910                  * rid of most of these :). */
2911
2912           int psuedoStkPtr=-1; 
2913           int firstTimeThruLoop = 1;
2914
2915                 _G.sendSet = reverseSet(_G.sendSet);
2916
2917                 /* First figure how many parameters are getting passed */
2918                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2919                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2920                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2921                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2922                 }
2923
2924                 stackParms = psuedoStkPtr;
2925
2926                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2927                   int size, offset = 0;
2928
2929                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2930                         size = AOP_SIZE(IC_LEFT(sic));
2931
2932                         while (size--) {
2933                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2934                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2935                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2936
2937                                 if(!firstTimeThruLoop) {
2938                                         /* If this is not the first time we've been through the loop
2939                                          * then we need to save the parameter in a temporary
2940                                          * register. The last byte of the last parameter is
2941                                          * passed in W. */
2942
2943                                         pushw();
2944                                         --psuedoStkPtr;         // sanity check
2945                                 }
2946                         
2947                                 firstTimeThruLoop=0;
2948
2949                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2950                                 offset++;
2951                         }
2952                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2953                 }
2954                 _G.sendSet = NULL;
2955         }
2956
2957         /* make the call */
2958         pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2959                         OP_SYMBOL(IC_LEFT(ic))->rname :
2960                         OP_SYMBOL(IC_LEFT(ic))->name));
2961
2962         GpsuedoStkPtr=0;
2963         /* if we need assign a result value */
2964         if ((IS_ITEMP(IC_RESULT(ic)) && 
2965                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2966                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2967                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2968
2969                 _G.accInUse++;
2970                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2971                 _G.accInUse--;
2972
2973                 assignResultValue(IC_RESULT(ic), 1);
2974
2975                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2976                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2977                 
2978                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2979         }
2980
2981         if(!stackParms && ic->parmBytes) {
2982                 stackParms = ic->parmBytes;
2983         }
2984         
2985         if(stackParms>0) {
2986                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2987                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2988                 if(STACK_MODEL_LARGE) {
2989                         emitSKPNC;
2990                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2991                 }
2992         }
2993
2994         /* adjust the stack for parameters if required */
2995 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2996 #if 0
2997         if (ic->parmBytes) {
2998           int i;
2999
3000                 if (ic->parmBytes > 3) {
3001                         pic16_emitcode("mov","a,%s",spname);
3002                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3003                         pic16_emitcode("mov","%s,a",spname);
3004                 } else 
3005                         for ( i = 0 ; i <  ic->parmBytes ;i++)
3006                                 pic16_emitcode("dec","%s",spname);
3007         }
3008 #endif
3009
3010 #if 0
3011         /* if register bank was saved then pop them */
3012         if (ic->bankSaved)
3013                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3014
3015         /* if we hade saved some registers then unsave them */
3016         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3017                 unsaveRegisters (ic);
3018 #endif
3019 }
3020
3021
3022
3023 /*-----------------------------------------------------------------*/   // patch 14
3024 /* genPcall - generates a call by pointer statement                */
3025 /*-----------------------------------------------------------------*/
3026
3027 // new version, created from genCall
3028
3029 static void genPcall (iCode *ic)
3030 {
3031   sym_link *dtype;   
3032   int stackParms=0;
3033   symbol *retlbl = newiTempLabel(NULL);
3034   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3035   
3036         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3037
3038         /* if caller saves & we have not saved then */
3039         if (!ic->regsSaved)
3040                 saveRegisters(ic);
3041
3042         /* if we are calling a function that is not using
3043          * the same register bank then we need to save the
3044          * destination registers on the stack */
3045         dtype = operandType(IC_LEFT(ic));
3046         if (currFunc && dtype && 
3047                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
3048                 IFFUNC_ISISR(currFunc->type) &&
3049                 !ic->bankSaved) 
3050
3051                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3052
3053         /* if send set is not empty the assign */
3054         if (_G.sendSet) {
3055           iCode *sic;
3056
3057                 /* For the Pic port, there is no data stack.
3058                  * So parameters passed to functions are stored
3059                  * in registers. (The pCode optimizer will get
3060                  * rid of most of these :). */
3061
3062           int psuedoStkPtr=-1; 
3063           int firstTimeThruLoop = 1;
3064
3065                 _G.sendSet = reverseSet(_G.sendSet);
3066
3067                 /* First figure how many parameters are getting passed */
3068                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3069                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3070                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
3071                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
3072                 }
3073
3074                 stackParms = psuedoStkPtr;
3075
3076                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3077                   int size, offset = 0;
3078
3079                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3080                         size = AOP_SIZE(IC_LEFT(sic));
3081
3082                         while (size--) {
3083                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3084                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3085                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3086
3087                                 if(!firstTimeThruLoop) {
3088                                         /* If this is not the first time we've been through the loop
3089                                          * then we need to save the parameter in a temporary
3090                                          * register. The last byte of the last parameter is
3091                                          * passed in W. */
3092
3093                                         pushw();
3094                                         --psuedoStkPtr;         // sanity check
3095                                 }
3096                         
3097                                 firstTimeThruLoop=0;
3098
3099                                 mov2w (AOP(IC_LEFT(sic)),  offset);
3100                                 offset++;
3101                         }
3102                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3103                 }
3104                 _G.sendSet = NULL;
3105         }
3106
3107         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3108
3109         // push return address
3110         // push $ on return stack, then replace with retlbl
3111
3112         pic16_emitpcodeNULLop(POC_PUSH);
3113
3114         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3115         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3116         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3117         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3118         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3119         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3120
3121         /* make the call by writing the pointer into pc */
3122         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3123         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3124
3125         // note: MOVFF to PCL not allowed
3126         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3127         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3128
3129
3130 //      pic16_emitpcode(POC_GOTO, pic16_popGetLabel(retlbl->key));
3131 //      pic16_emitpcodeNULLop(POC_NOP);
3132 //      pic16_emitpcodeNULLop(POC_NOP);
3133
3134         /* return address is here: (X) */
3135         pic16_emitpLabelFORCE(retlbl->key);
3136
3137 //      pic16_emitpcodeNULLop(POC_NOP);
3138
3139         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3140
3141         GpsuedoStkPtr=0;
3142         /* if we need assign a result value */
3143         if ((IS_ITEMP(IC_RESULT(ic)) && 
3144                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3145                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
3146                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3147
3148                 _G.accInUse++;
3149                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3150                 _G.accInUse--;
3151
3152                 assignResultValue(IC_RESULT(ic), 1);
3153
3154                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3155                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3156                 
3157                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3158         }
3159
3160         if(stackParms>0) {
3161                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3162                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3163                 if(STACK_MODEL_LARGE) {
3164                         emitSKPNC;
3165                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3166                 }
3167         }
3168
3169         /* adjust the stack for parameters if required */
3170 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3171
3172         if (ic->parmBytes) {
3173           int i;
3174
3175                 if (ic->parmBytes > 3) {
3176                         pic16_emitcode("mov","a,%s",spname);
3177                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3178                         pic16_emitcode("mov","%s,a",spname);
3179                 } else 
3180                         for ( i = 0 ; i <  ic->parmBytes ;i++)
3181                                 pic16_emitcode("dec","%s",spname);
3182         }
3183
3184         /* if register bank was saved then pop them */
3185         if (ic->bankSaved)
3186                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3187
3188         /* if we hade saved some registers then unsave them */
3189         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3190                 unsaveRegisters (ic);
3191 }
3192
3193
3194 #if 0                                                                           // patch 14
3195 // old version, kept for reference
3196
3197 /*-----------------------------------------------------------------*/
3198 /* genPcall - generates a call by pointer statement                */
3199 /*-----------------------------------------------------------------*/
3200 static void genPcall (iCode *ic)
3201 {
3202     sym_link *dtype;
3203     symbol *rlbl = newiTempLabel(NULL);
3204
3205
3206     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3207     /* if caller saves & we have not saved then */
3208     if (!ic->regsSaved)
3209         saveRegisters(ic);
3210
3211     /* if we are calling a function that is not using
3212     the same register bank then we need to save the
3213     destination registers on the stack */
3214     dtype = operandType(IC_LEFT(ic));
3215     if (currFunc && dtype && 
3216         IFFUNC_ISISR(currFunc->type) &&
3217         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3218         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3219
3220
3221     /* push the return address on to the stack */
3222     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3223     pic16_emitcode("push","acc");    
3224     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3225     pic16_emitcode("push","acc");
3226     
3227     if (options.model == MODEL_FLAT24)
3228     {
3229         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3230         pic16_emitcode("push","acc");    
3231     }
3232
3233     /* now push the calling address */
3234     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3235
3236     pushSide(IC_LEFT(ic), FPTRSIZE);
3237
3238     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
3239
3240     /* if send set is not empty the assign */
3241     if (_G.sendSet) {
3242         iCode *sic ;
3243
3244         for (sic = setFirstItem(_G.sendSet) ; sic ; 
3245              sic = setNextItem(_G.sendSet)) {
3246             int size, offset = 0;
3247             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3248             size = AOP_SIZE(IC_LEFT(sic));
3249             while (size--) {
3250                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3251                                 FALSE,FALSE);
3252                 if (strcmp(l,fReturn[offset]))
3253                     pic16_emitcode("mov","%s,%s",
3254                              fReturn[offset],
3255                              l);
3256                 offset++;
3257             }
3258             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3259         }
3260         _G.sendSet = NULL;
3261     }
3262
3263     pic16_emitcode("ret","");
3264     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3265
3266
3267     /* if we need assign a result value */
3268     if ((IS_ITEMP(IC_RESULT(ic)) &&
3269          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3270           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3271         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3272
3273         _G.accInUse++;
3274         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3275         _G.accInUse--;
3276         
3277         assignResultValue(IC_RESULT(ic), 1);
3278
3279         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3280     }
3281
3282     /* adjust the stack for parameters if 
3283     required */
3284     if (ic->parmBytes) {
3285         int i;
3286         if (ic->parmBytes > 3) {
3287             pic16_emitcode("mov","a,%s",spname);
3288             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3289             pic16_emitcode("mov","%s,a",spname);
3290         } else 
3291             for ( i = 0 ; i <  ic->parmBytes ;i++)
3292                 pic16_emitcode("dec","%s",spname);
3293
3294     }
3295
3296     /* if register bank was saved then unsave them */
3297     if (currFunc && dtype && 
3298         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3299         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3300
3301     /* if we hade saved some registers then
3302     unsave them */
3303     if (ic->regsSaved)
3304         unsaveRegisters (ic);
3305
3306 }
3307 #endif                                                                          // patch 14
3308
3309
3310 /*-----------------------------------------------------------------*/
3311 /* resultRemat - result  is rematerializable                       */
3312 /*-----------------------------------------------------------------*/
3313 static int resultRemat (iCode *ic)
3314 {
3315   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3316   if (SKIP_IC(ic) || ic->op == IFX)
3317     return 0;
3318
3319   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3320     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3321     if (sym->remat && !POINTER_SET(ic)) 
3322       return 1;
3323   }
3324
3325   return 0;
3326 }
3327
3328 #if defined(__BORLANDC__) || defined(_MSC_VER)
3329 #define STRCASECMP stricmp
3330 #else
3331 #define STRCASECMP strcasecmp
3332 #endif
3333
3334 #if 0
3335 /*-----------------------------------------------------------------*/
3336 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3337 /*-----------------------------------------------------------------*/
3338 static bool inExcludeList(char *s)
3339 {
3340   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3341     int i =0;
3342     
3343     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3344     if (options.excludeRegs[i] &&
3345     STRCASECMP(options.excludeRegs[i],"none") == 0)
3346         return FALSE ;
3347
3348     for ( i = 0 ; options.excludeRegs[i]; i++) {
3349         if (options.excludeRegs[i] &&
3350         STRCASECMP(s,options.excludeRegs[i]) == 0)
3351             return TRUE;
3352     }
3353     return FALSE ;
3354 }
3355 #endif
3356
3357 /*-----------------------------------------------------------------*/
3358 /* genFunction - generated code for function entry                 */
3359 /*-----------------------------------------------------------------*/
3360 static void genFunction (iCode *ic)
3361 {
3362   symbol *sym;
3363   sym_link *ftype;
3364   
3365         DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3366
3367         pic16_labelOffset += (max_key+4);
3368         max_key=0;
3369         GpsuedoStkPtr=0;
3370         _G.nRegsSaved = 0;
3371
3372         ftype = operandType(IC_LEFT(ic));
3373         sym = OP_SYMBOL(IC_LEFT(ic));
3374
3375         if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3376                 /* create an absolute section at the interrupt vector:
3377                  * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3378           symbol *asym;
3379           char asymname[128];
3380           pBlock *apb;
3381
3382                 {
3383                   int i, found=-1;
3384
3385                         sym = OP_SYMBOL( IC_LEFT(ic));
3386                         for(i=0;i<=2;i++) {
3387                                 if(interrupts[i]->name
3388                                         && !STRCASECMP(interrupts[i]->name, sym->name)) {
3389                                         found = i;
3390                                         break;
3391                                 }
3392                         }
3393                         
3394                         if(found == -1) {
3395                                 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3396                                         __FILE__, __LINE__, sym->name);
3397                                 assert( 0 );
3398                         }
3399                         _G.interruptvector = found;
3400                 }
3401
3402                 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3403                 asym = newSymbol(asymname, 0);
3404
3405                 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3406                 pic16_addpBlock( apb );
3407
3408                 pic16_addpCode2pBlock(apb,
3409                         pic16_newpCodeCharP(";-----------------------------------------"));
3410
3411
3412                 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3413
3414                 pic16_addpCode2pBlock(apb,
3415                         pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3416                 
3417                 /* mark the end of this tiny function */
3418                 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3419
3420                 {
3421                   absSym *abSym;
3422
3423                         abSym = Safe_calloc(1, sizeof(absSym));
3424                         abSym->name = Safe_strdup( asymname );
3425
3426                         switch( _G.interruptvector ) {
3427                                 case 0: abSym->address = 0x000000; break;
3428                                 case 1: abSym->address = 0x000008; break;
3429                                 case 2: abSym->address = 0x000018; break;
3430                         }
3431
3432                         /* relocate interrupt vectors if needed */
3433                         abSym->address += pic16_options.ivt_loc;
3434
3435                         addSet(&absSymSet, abSym);
3436                 }
3437         }
3438
3439
3440         /* create the function header */
3441         pic16_emitcode(";","-----------------------------------------");
3442         pic16_emitcode(";"," function %s",sym->name);
3443         pic16_emitcode(";","-----------------------------------------");
3444
3445         pic16_emitcode("","%s:",sym->rname);
3446         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3447
3448
3449         {
3450           absSym *ab;
3451
3452                 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3453                         if(!strcmp(ab->name, sym->name)) {
3454                                 pic16_pBlockConvert2Absolute(pb);
3455                                 break;
3456                         }
3457
3458         }
3459
3460
3461         if(IFFUNC_ISNAKED(ftype)) {
3462                 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3463                 return;
3464         }
3465         
3466         /* if critical function then turn interrupts off */
3467         if (IFFUNC_ISCRITICAL(ftype))
3468                 pic16_emitcode("clr","ea");
3469
3470         /* if this is an interrupt service routine then
3471          * save acc, b, dpl, dph  */
3472         if (IFFUNC_ISISR(sym->type)) {
3473           int i;
3474
3475                 _G.usefastretfie = 1;   /* use shadow registers by default */
3476                 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3477                 if(!(_G.interruptvector == 1)) {
3478
3479                         /* do not save WREG,STATUS,BSR for high priority interrupts
3480                          * because they are stored in the hardware shadow registers already */
3481                         _G.usefastretfie = 0;
3482                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3483                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3484                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3485                 }
3486
3487
3488                 /* these should really be optimized somehow, because not all
3489                  * interrupt handlers modify them */
3490                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3491                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3492                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3493                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3494
3495 //                pic16_pBlockConvert2ISR(pb);
3496                 
3497                 /* if any registers used */
3498                 if (sym->regsUsed) {
3499                         /* save the registers used */
3500                         DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3501                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3502                                 if (bitVectBitValue(sym->regsUsed,i)) {
3503 #if 0
3504                                         fprintf(stderr, "%s:%d function %s uses register %s\n",
3505                                                         __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3506                                                         pic16_regWithIdx(i)->name);
3507 #endif
3508
3509                                         pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3510                                         _G.nRegsSaved++;
3511
3512                                         if(!pic16_regWithIdx(i)->wasUsed) {
3513                                                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3514                                                         __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3515
3516                                                 pic16_regWithIdx(i)->wasUsed = 1;
3517                                         }
3518                                 }
3519                         }
3520                 }
3521         } else {
3522                 /* emit code to setup stack frame if user enabled,
3523                  * and function is not main() */
3524          
3525 //              fprintf(stderr, "function name: %s\n", sym->name);
3526                 if(strcmp(sym->name, "main")) {
3527                         if(/*!options.ommitFramePtr || */sym->regsUsed) {
3528                         /* setup the stack frame */
3529                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3530                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3531                                 if(STACK_MODEL_LARGE)
3532                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3533                         }
3534                 }
3535
3536                 /* if callee-save to be used for this function
3537                 * then save the registers being used in this function */
3538 //              if (IFFUNC_CALLEESAVES(sym->type))
3539                 {
3540                   int i;
3541
3542 //                      fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3543
3544 //                      pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3545
3546                         /* if any registers used */
3547                         if (sym->regsUsed) {
3548                                 /* save the registers used */
3549                                 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3550                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3551                                         if (bitVectBitValue(sym->regsUsed,i)) {
3552
3553 #if 0
3554                                                 fprintf(stderr, "%s:%d function %s uses register %s (wasUsed: %d, %p)\n",
3555                                                                 __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3556                                                                 pic16_regWithIdx(i)->name,
3557                                                                 pic16_regWithIdx(i)->wasUsed,
3558                                                                 pic16_regWithIdx(i));
3559 #endif
3560
3561                                                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3562
3563 //                                              pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3564 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3565 //                                                      &pic16_pc_postdec1, 0));
3566
3567                                                 _G.nRegsSaved++;
3568
3569                                                 if(!pic16_regWithIdx(i)->wasUsed) {
3570                                                         fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3571                                                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3572
3573                                                         pic16_regWithIdx(i)->wasUsed = 1;
3574                                                 }
3575                                         
3576                                         }
3577                                 }
3578                         }
3579                 }
3580         }
3581
3582
3583         
3584 #if 0
3585         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3586
3587                 if (options.useXstack) {
3588                         pic16_emitcode("mov","r0,%s",spname);
3589                         pic16_emitcode("mov","a,_bp");
3590                         pic16_emitcode("movx","@r0,a");
3591                         pic16_emitcode("inc","%s",spname);
3592                 } else {
3593                         /* set up the stack */
3594                         pic16_emitcode ("push","_bp");     /* save the callers stack  */
3595                 }
3596                 pic16_emitcode ("mov","_bp,%s",spname);
3597         }
3598 #endif
3599         DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3600
3601         /* adjust the stack for the function */
3602         if (sym->stack) {
3603           int i = sym->stack;
3604
3605                 if (i > 127 ) 
3606                         werror(W_STACK_OVERFLOW,sym->name);
3607
3608                 if (i > 3 && sym->recvSize < 4) {              
3609                         pic16_emitcode ("mov","a,sp");
3610                         pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3611                         pic16_emitcode ("mov","sp,a");
3612                 } else
3613                         while(i--)
3614                                 pic16_emitcode("inc","sp");
3615         }
3616
3617         if (sym->xstack) {
3618                 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3619
3620                 pic16_emitcode ("mov","a,_spx");
3621                 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3622                 pic16_emitcode ("mov","_spx,a");
3623         }
3624     
3625 }
3626
3627 /*-----------------------------------------------------------------*/
3628 /* genEndFunction - generates epilogue for functions               */
3629 /*-----------------------------------------------------------------*/
3630 static void genEndFunction (iCode *ic)
3631 {
3632     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3633
3634     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3635
3636     if(IFFUNC_ISNAKED(sym->type)) {
3637         DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3638         return;
3639     }
3640
3641     /* add code for ISCRITICAL */
3642
3643 #if 0
3644     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3645     {
3646         pic16_emitcode ("mov","%s,_bp",spname);
3647     }
3648 #endif
3649
3650     /* if use external stack but some variables were
3651     added to the local stack then decrement the
3652     local stack */
3653     if (options.useXstack && sym->stack) {      
3654         pic16_emitcode("mov","a,sp");
3655         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3656         pic16_emitcode("mov","sp,a");
3657     }
3658
3659
3660 #if 0
3661     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3662         if (options.useXstack) {
3663             pic16_emitcode("mov","r0,%s",spname);
3664             pic16_emitcode("movx","a,@r0");
3665             pic16_emitcode("mov","_bp,a");
3666             pic16_emitcode("dec","%s",spname);
3667         }
3668         else
3669         {
3670             pic16_emitcode ("pop","_bp");
3671         }
3672     }
3673 #endif
3674
3675         if (IFFUNC_ISISR(sym->type)) {
3676                 /* now we need to restore the registers */
3677                 /* if any registers used */
3678                 if (sym->regsUsed) {
3679                   int i;
3680
3681                         /* restore registers used */
3682                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3683                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3684                                 if (bitVectBitValue(sym->regsUsed,i)) {
3685
3686 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3687 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3688 //                                                      pic16_regWithIdx(i)->name);
3689
3690                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3691
3692 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3693 //                                                      &pic16_pc_preinc1,
3694 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3695
3696                                 }
3697                         }
3698                 }
3699         
3700                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3701                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3702                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3703                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3704
3705                 if(!(_G.interruptvector == 1)) {
3706                         /* do not restore interrupt vector for WREG,STATUS,BSR
3707                          * for high priority interrupt, see genFunction */
3708                          
3709                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3710                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3711                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3712                 }
3713         
3714                 _G.interruptvector = 0;         /* sanity check */
3715
3716 //              pic16_pBlockConvert2ISR(pb);
3717
3718
3719                 /* if debug then send end of function */
3720 /*      if (options.debug && currFunc)  */
3721                 if (currFunc) {
3722                         debugFile->writeEndFunction (currFunc, ic, 1);
3723                 }
3724         
3725                 if(_G.usefastretfie)
3726                         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3727                 else
3728                 pic16_emitpcodeNULLop(POC_RETFIE);
3729                 _G.usefastretfie = 0;
3730         } else {
3731                 if (IFFUNC_ISCRITICAL(sym->type))
3732                         pic16_emitcode("setb","ea");
3733         
3734
3735 //              pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3736
3737                 /* if any registers used */
3738                 if (sym->regsUsed) {
3739                   int i;
3740                         /* save the registers used */
3741                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3742                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3743                                 if (bitVectBitValue(sym->regsUsed,i)) {
3744         
3745 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3746 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3747 //                                                      pic16_regWithIdx(i)->name);
3748         
3749                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3750                                         
3751 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3752 //                                              &pic16_pc_preinc1,
3753 //                                              PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3754
3755                                         _G.nRegsSaved--;
3756                                 }
3757                         }
3758                 }
3759         
3760 //              pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3761                 /* if debug then send end of function */
3762                 if (currFunc) {
3763                         debugFile->writeEndFunction (currFunc, ic, 1);
3764                 }
3765
3766                 /* insert code to restore stack frame, if user enabled it
3767                  * and function is not main() */
3768          
3769
3770                 if(strcmp(sym->name, "main")) {
3771                         if(/*!options.ommitFramePtr ||*/ sym->regsUsed) {
3772                                 /* restore stack frame */
3773                                 if(STACK_MODEL_LARGE)
3774                                         pic16_emitpcode(POC_MOVFF,
3775                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3776                                 pic16_emitpcode(POC_MOVFF,
3777                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3778                         }
3779                 }
3780
3781                 pic16_emitpcodeNULLop(POC_RETURN);
3782
3783                 /* Mark the end of a function */
3784                 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3785         }
3786
3787 }
3788
3789
3790 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3791 {
3792
3793         if(is_LitOp(op)) {
3794                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3795
3796                 if(dest->type != PO_WREG)
3797                         pic16_emitpcode(POC_MOVWF, dest);
3798         } else {
3799                 if(dest->type == PO_WREG && (offset == 0)) {
3800                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3801                         return;
3802                 }
3803                 
3804                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3805                         pic16_popGet(AOP(op), offset), dest));
3806         }
3807 }
3808
3809 /*-----------------------------------------------------------------*/
3810 /* genRet - generate code for return statement                     */
3811 /*-----------------------------------------------------------------*/
3812 static void genRet (iCode *ic)
3813 {
3814   int size;
3815   operand *left;
3816
3817         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3818         /* if we have no return value then
3819          * just generate the "ret" */
3820         
3821         if (!IC_LEFT(ic)) 
3822                 goto jumpret;       
3823     
3824         /* we have something to return then
3825          * move the return value into place */
3826         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3827         size = AOP_SIZE(IC_LEFT(ic));
3828
3829         if(size <= 4) {
3830                 if(size>3) {
3831                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3832 //                      pic16_emitpcode(POC_MOVFF,
3833 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3834                 }
3835                 if(size>2) {
3836                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3837 //                      pic16_emitpcode(POC_MOVFF,
3838 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3839                 }
3840                 if(size>1) {
3841                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3842 //                      pic16_emitpcode(POC_MOVFF,
3843 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3844                 }
3845
3846 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3847
3848                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3849 //              pic16_emitpcode(POC_MOVFF,
3850 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3851
3852         } else {
3853                 /* >32-bits, setup stack and FSR0 */
3854                 while (size--) {
3855 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3856 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3857
3858                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3859
3860 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3861                         GpsuedoStkPtr++;
3862                 }
3863                         
3864                 /* setup FSR0 */
3865                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3866                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3867
3868                 if(STACK_MODEL_LARGE) {
3869                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3870                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3871                 } else {
3872                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3873                 }
3874         }
3875                                 
3876 #if 0
3877         /* old code, left here for reference -- VR */    
3878         while (size--) {
3879           char *l ;
3880
3881                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3882                         /* #NOCHANGE */
3883                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3884                         pic16_emitpcomment("push %s",l);
3885                         pushed++;
3886                 } else {
3887                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3888                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3889                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3890                         
3891                         if (strcmp(fReturn[offset],l)) {
3892                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3893                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3894                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3895                                 } else {
3896                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3897                                 }
3898                                 
3899                                 if(size) {
3900                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3901                                 }
3902                                 offset++;
3903                         }
3904                 }
3905         }    
3906
3907         if (pushed) {
3908                 while(pushed) {
3909                         pushed--;
3910                         if (strcmp(fReturn[pushed],"a"))
3911                                 pic16_emitcode("pop",fReturn[pushed]);
3912                         else
3913                                 pic16_emitcode("pop","acc");
3914                 }
3915         }
3916 #endif
3917
3918
3919         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3920     
3921 jumpret:
3922         /* generate a jump to the return label
3923          * if the next is not the return statement */
3924         if (!(ic->next && ic->next->op == LABEL
3925                 && IC_LABEL(ic->next) == returnLabel)) {
3926         
3927                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3928                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3929         }
3930 }
3931
3932 /*-----------------------------------------------------------------*/
3933 /* genLabel - generates a label                                    */
3934 /*-----------------------------------------------------------------*/
3935 static void genLabel (iCode *ic)
3936 {
3937
3938
3939     /* special case never generate */
3940     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3941     if (IC_LABEL(ic) == entryLabel)
3942         return ;
3943
3944     pic16_emitpLabel(IC_LABEL(ic)->key);
3945     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3946 }
3947
3948 /*-----------------------------------------------------------------*/
3949 /* genGoto - generates a goto                                      */
3950 /*-----------------------------------------------------------------*/
3951 //tsd
3952 static void genGoto (iCode *ic)
3953 {
3954   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3955   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3956 }
3957
3958
3959 /*-----------------------------------------------------------------*/
3960 /* genMultbits :- multiplication of bits                           */
3961 /*-----------------------------------------------------------------*/
3962 static void genMultbits (operand *left, 
3963                          operand *right, 
3964                          operand *result)
3965 {
3966   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3967
3968   if(!pic16_sameRegs(AOP(result),AOP(right)))
3969     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3970
3971   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3972   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3973   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3974
3975 }
3976
3977
3978 /*-----------------------------------------------------------------*/
3979 /* genMultOneByte : 8 bit multiplication & division                */
3980 /*-----------------------------------------------------------------*/
3981 static void genMultOneByte (operand *left,
3982                             operand *right,
3983                             operand *result)
3984 {
3985
3986   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3987   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3988   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3989
3990   /* (if two literals, the value is computed before) */
3991   /* if one literal, literal on the right */
3992   if (AOP_TYPE(left) == AOP_LIT){
3993     operand *t = right;
3994     right = left;
3995     left = t;
3996   }
3997
3998         /* size is already checked in genMult == 1 */
3999 //      size = AOP_SIZE(result);
4000
4001         if (AOP_TYPE(right) == AOP_LIT){
4002                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4003                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4004                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4005                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4006         } else {
4007                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4008                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4009                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4010                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4011         }
4012         
4013         pic16_genMult8X8_8 (left, right,result);
4014 }
4015
4016 /*-----------------------------------------------------------------*/
4017 /* genMultOneWord : 16 bit multiplication                          */
4018 /*-----------------------------------------------------------------*/
4019 static void genMultOneWord (operand *left,
4020                             operand *right,
4021                             operand *result)
4022 {
4023
4024         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4025         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4026         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4027
4028         /* (if two literals, the value is computed before)
4029          * if one literal, literal on the right */
4030         if (AOP_TYPE(left) == AOP_LIT){
4031           operand *t = right;
4032                 right = left;
4033                 left = t;
4034         }
4035
4036         /* size is checked already == 2 */
4037 //      size = AOP_SIZE(result);
4038
4039         if (AOP_TYPE(right) == AOP_LIT) {
4040                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4041                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4042                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4043                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4044         } else {
4045                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4046                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4047                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4048                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4049         }
4050         
4051         pic16_genMult16X16_16(left, right,result);
4052 }
4053
4054 /*-----------------------------------------------------------------*/
4055 /* genMultOneLong : 32 bit multiplication                          */
4056 /*-----------------------------------------------------------------*/
4057 static void genMultOneLong (operand *left,
4058                             operand *right,
4059                             operand *result)
4060 {
4061
4062         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4063         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4064         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4065
4066         /* (if two literals, the value is computed before)
4067          * if one literal, literal on the right */
4068         if (AOP_TYPE(left) == AOP_LIT){
4069           operand *t = right;
4070                 right = left;
4071                 left = t;
4072         }
4073
4074         /* size is checked already == 4 */
4075 //      size = AOP_SIZE(result);
4076
4077         if (AOP_TYPE(right) == AOP_LIT) {
4078                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4079                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4080                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4081                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4082         } else {
4083                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4084                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4085                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4086                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4087         }
4088         
4089         pic16_genMult32X32_32(left, right,result);
4090 }
4091
4092
4093
4094 /*-----------------------------------------------------------------*/
4095 /* genMult - generates code for multiplication                     */
4096 /*-----------------------------------------------------------------*/
4097 static void genMult (iCode *ic)
4098 {
4099   operand *left = IC_LEFT(ic);
4100   operand *right = IC_RIGHT(ic);
4101   operand *result= IC_RESULT(ic);   
4102
4103         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4104         /* assign the amsops */
4105         pic16_aopOp (left,ic,FALSE);
4106         pic16_aopOp (right,ic,FALSE);
4107         pic16_aopOp (result,ic,TRUE);
4108
4109         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4110
4111         /* special cases first *
4112         * both are bits */
4113         if (AOP_TYPE(left) == AOP_CRY
4114                 && AOP_TYPE(right)== AOP_CRY) {
4115                 genMultbits(left,right,result);
4116           goto release ;
4117         }
4118
4119         /* if both are of size == 1 */
4120         if(AOP_SIZE(left) == 1
4121                 && AOP_SIZE(right) == 1) {
4122                 genMultOneByte(left,right,result);
4123           goto release ;
4124         }
4125
4126         /* if both are of size == 2 */
4127         if(AOP_SIZE(left) == 2
4128                 && AOP_SIZE(right) == 2) {
4129                 genMultOneWord(left, right, result);
4130           goto release;
4131         }
4132         
4133         /* if both are of size == 4 */
4134         if(AOP_SIZE(left) == 4
4135                 && AOP_SIZE(right) == 4) {
4136                 genMultOneLong(left, right, result);
4137           goto release;
4138         }
4139         
4140         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4141
4142
4143         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4144         /* should have been converted to function call */
4145         assert(0) ;
4146
4147 release :
4148         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4149         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4150         pic16_freeAsmop(result,NULL,ic,TRUE); 
4151 }
4152
4153 /*-----------------------------------------------------------------*/
4154 /* genDivbits :- division of bits                                  */
4155 /*-----------------------------------------------------------------*/
4156 static void genDivbits (operand *left, 
4157                         operand *right, 
4158                         operand *result)
4159 {
4160
4161     char *l;
4162
4163     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4164     /* the result must be bit */    
4165     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4166     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4167
4168     MOVA(l);    
4169
4170     pic16_emitcode("div","ab");
4171     pic16_emitcode("rrc","a");
4172     pic16_aopPut(AOP(result),"c",0);
4173 }
4174
4175 /*-----------------------------------------------------------------*/
4176 /* genDivOneByte : 8 bit division                                  */
4177 /*-----------------------------------------------------------------*/
4178 static void genDivOneByte (operand *left,
4179                            operand *right,
4180                            operand *result)
4181 {
4182     sym_link *opetype = operandType(result);
4183     char *l ;
4184     symbol *lbl ;
4185     int size,offset;
4186
4187         /* result = divident / divisor
4188          * - divident may be a register or a literal,
4189          * - divisor may be a register or a literal,
4190          * so there are 3 cases (literal / literal is optimized
4191          * by the front-end) to handle.
4192          * In addition we must handle signed and unsigned, which
4193          * result in 6 final different cases -- VR */
4194
4195     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4196     size = AOP_SIZE(result) - 1;
4197     offset = 1;
4198     /* signed or unsigned */
4199     if (SPEC_USIGN(opetype)) {
4200       pCodeOp *pct1,    /* count */
4201                 *pct2,  /* reste */
4202                 *pct3;  /* temp */
4203       symbol *label1, *label2, *label3;;
4204
4205
4206         /* unsigned is easy */
4207
4208         pct1 = pic16_popGetTempReg();
4209         pct2 = pic16_popGetTempReg();
4210         pct3 = pic16_popGetTempReg();
4211         
4212         label1 = newiTempLabel(NULL);
4213         label2 = newiTempLabel(NULL);
4214         label3 = newiTempLabel(NULL);
4215
4216         /* the following algorithm is extracted from divuint.c */
4217
4218         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4219         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4220         
4221         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4222
4223         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4224         
4225         pic16_emitpLabel(label1->key);
4226         
4227         emitCLRC;
4228         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4229
4230
4231         emitCLRC;
4232         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4233         
4234
4235         emitSKPNC;
4236         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4237         
4238         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4239         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4240         
4241         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4242         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4243         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4244         
4245         pic16_emitpLabel( label3->key );
4246         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4247         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4248         
4249         
4250
4251         pic16_emitpLabel(label2->key);
4252         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4253         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4254         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4255         
4256         /* result is in wreg */
4257         if(AOP_TYPE(result) != AOP_ACC)
4258                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4259
4260         pic16_popReleaseTempReg( pct3 );
4261         pic16_popReleaseTempReg( pct2 );
4262         pic16_popReleaseTempReg( pct1 );
4263
4264         return ;
4265     }
4266
4267     /* signed is a little bit more difficult */
4268
4269     /* save the signs of the operands */
4270     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4271     MOVA(l);    
4272     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4273     pic16_emitcode("push","acc"); /* save it on the stack */
4274
4275     /* now sign adjust for both left & right */
4276     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4277     MOVA(l);       
4278     lbl = newiTempLabel(NULL);
4279     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4280     pic16_emitcode("cpl","a");   
4281     pic16_emitcode("inc","a");
4282     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4283     pic16_emitcode("mov","b,a");
4284
4285     /* sign adjust left side */
4286     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4287     MOVA(l);
4288
4289     lbl = newiTempLabel(NULL);
4290     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4291     pic16_emitcode("cpl","a");
4292     pic16_emitcode("inc","a");
4293     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4294
4295     /* now the division */
4296     pic16_emitcode("div","ab");
4297     /* we are interested in the lower order
4298     only */
4299     pic16_emitcode("mov","b,a");
4300     lbl = newiTempLabel(NULL);
4301     pic16_emitcode("pop","acc");   
4302     /* if there was an over flow we don't 
4303     adjust the sign of the result */
4304     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4305     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4306     CLRC;
4307     pic16_emitcode("clr","a");
4308     pic16_emitcode("subb","a,b");
4309     pic16_emitcode("mov","b,a");
4310     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4311
4312     /* now we are done */
4313     pic16_aopPut(AOP(result),"b",0);
4314     if(size > 0){
4315         pic16_emitcode("mov","c,b.7");
4316         pic16_emitcode("subb","a,acc");   
4317     }
4318     while (size--)
4319         pic16_aopPut(AOP(result),"a",offset++);
4320
4321 }
4322
4323 /*-----------------------------------------------------------------*/
4324 /* genDiv - generates code for division                            */
4325 /*-----------------------------------------------------------------*/
4326 static void genDiv (iCode *ic)
4327 {
4328     operand *left = IC_LEFT(ic);
4329     operand *right = IC_RIGHT(ic);
4330     operand *result= IC_RESULT(ic);   
4331
4332
4333         /* Division is a very lengthy algorithm, so it is better
4334          * to call support routines than inlining algorithm.
4335          * Division functions written here just in case someone
4336          * wants to inline and not use the support libraries -- VR */
4337
4338     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4339     /* assign the amsops */
4340     pic16_aopOp (left,ic,FALSE);
4341     pic16_aopOp (right,ic,FALSE);
4342     pic16_aopOp (result,ic,TRUE);
4343
4344     /* special cases first */
4345     /* both are bits */
4346     if (AOP_TYPE(left) == AOP_CRY &&
4347         AOP_TYPE(right)== AOP_CRY) {
4348         genDivbits(left,right,result);
4349         goto release ;
4350     }
4351
4352     /* if both are of size == 1 */
4353     if (AOP_SIZE(left) == 1 &&
4354         AOP_SIZE(right) == 1 ) {
4355         genDivOneByte(left,right,result);
4356         goto release ;
4357     }
4358
4359     /* should have been converted to function call */
4360     assert(0);
4361 release :
4362     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4363     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4364     pic16_freeAsmop(result,NULL,ic,TRUE); 
4365 }
4366
4367 /*-----------------------------------------------------------------*/
4368 /* genModbits :- modulus of bits                                   */
4369 /*-----------------------------------------------------------------*/
4370 static void genModbits (operand *left, 
4371                         operand *right, 
4372                         operand *result)
4373 {
4374
4375     char *l;
4376
4377     /* the result must be bit */    
4378     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4379     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4380
4381     MOVA(l);       
4382
4383     pic16_emitcode("div","ab");
4384     pic16_emitcode("mov","a,b");
4385     pic16_emitcode("rrc","a");
4386     pic16_aopPut(AOP(result),"c",0);
4387 }
4388
4389 /*-----------------------------------------------------------------*/
4390 /* genModOneByte : 8 bit modulus                                   */
4391 /*-----------------------------------------------------------------*/
4392 static void genModOneByte (operand *left,
4393                            operand *right,
4394                            operand *result)
4395 {
4396     sym_link *opetype = operandType(result);
4397     char *l ;
4398     symbol *lbl ;
4399
4400     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4401     /* signed or unsigned */
4402     if (SPEC_USIGN(opetype)) {
4403         /* unsigned is easy */
4404         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4405         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4406         MOVA(l);    
4407         pic16_emitcode("div","ab");
4408         pic16_aopPut(AOP(result),"b",0);
4409         return ;
4410     }
4411
4412     /* signed is a little bit more difficult */
4413
4414     /* save the signs of the operands */
4415     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4416     MOVA(l);
4417
4418     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4419     pic16_emitcode("push","acc"); /* save it on the stack */
4420
4421     /* now sign adjust for both left & right */
4422     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4423     MOVA(l);
4424
4425     lbl = newiTempLabel(NULL);
4426     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4427     pic16_emitcode("cpl","a");   
4428     pic16_emitcode("inc","a");
4429     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4430     pic16_emitcode("mov","b,a"); 
4431
4432     /* sign adjust left side */
4433     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4434     MOVA(l);
4435
4436     lbl = newiTempLabel(NULL);
4437     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4438     pic16_emitcode("cpl","a");   
4439     pic16_emitcode("inc","a");
4440     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4441
4442     /* now the multiplication */
4443     pic16_emitcode("div","ab");
4444     /* we are interested in the lower order
4445     only */
4446     lbl = newiTempLabel(NULL);
4447     pic16_emitcode("pop","acc");   
4448     /* if there was an over flow we don't 
4449     adjust the sign of the result */
4450     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4451     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4452     CLRC ;
4453     pic16_emitcode("clr","a");
4454     pic16_emitcode("subb","a,b");
4455     pic16_emitcode("mov","b,a");
4456     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4457
4458     /* now we are done */
4459     pic16_aopPut(AOP(result),"b",0);
4460
4461 }
4462
4463 /*-----------------------------------------------------------------*/
4464 /* genMod - generates code for division                            */
4465 /*-----------------------------------------------------------------*/
4466 static void genMod (iCode *ic)
4467 {
4468     operand *left = IC_LEFT(ic);
4469     operand *right = IC_RIGHT(ic);
4470     operand *result= IC_RESULT(ic);  
4471
4472     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4473     /* assign the amsops */
4474     pic16_aopOp (left,ic,FALSE);
4475     pic16_aopOp (right,ic,FALSE);
4476     pic16_aopOp (result,ic,TRUE);
4477
4478     /* special cases first */
4479     /* both are bits */
4480     if (AOP_TYPE(left) == AOP_CRY &&
4481         AOP_TYPE(right)== AOP_CRY) {
4482         genModbits(left,right,result);
4483         goto release ;
4484     }
4485
4486     /* if both are of size == 1 */
4487     if (AOP_SIZE(left) == 1 &&
4488         AOP_SIZE(right) == 1 ) {
4489         genModOneByte(left,right,result);
4490         goto release ;
4491     }
4492
4493     /* should have been converted to function call */
4494     assert(0);
4495
4496 release :
4497     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4498     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4499     pic16_freeAsmop(result,NULL,ic,TRUE); 
4500 }
4501
4502 /*-----------------------------------------------------------------*/
4503 /* genIfxJump :- will create a jump depending on the ifx           */
4504 /*-----------------------------------------------------------------*/
4505 /*
4506   note: May need to add parameter to indicate when a variable is in bit space.
4507 */
4508 static void genIfxJump (iCode *ic, char *jval)
4509 {
4510
4511     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4512     /* if true label then we jump if condition
4513     supplied is true */
4514     if ( IC_TRUE(ic) ) {
4515
4516         if(strcmp(jval,"a") == 0)
4517           emitSKPZ;
4518         else if (strcmp(jval,"c") == 0)
4519           emitSKPC;
4520         else {
4521           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4522           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4523         }
4524
4525         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4526         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4527
4528     }
4529     else {
4530         /* false label is present */
4531         if(strcmp(jval,"a") == 0)
4532           emitSKPNZ;
4533         else if (strcmp(jval,"c") == 0)
4534           emitSKPNC;
4535         else {
4536           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4537           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4538         }
4539
4540         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4541         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4542
4543     }
4544
4545
4546     /* mark the icode as generated */
4547     ic->generated = 1;
4548 }
4549
4550 #if 0
4551 // not needed ATM
4552
4553 /*-----------------------------------------------------------------*/
4554 /* genSkip                                                         */
4555 /*-----------------------------------------------------------------*/
4556 static void genSkip(iCode *ifx,int status_bit)
4557 {
4558   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4559   if(!ifx)
4560     return;
4561
4562   if ( IC_TRUE(ifx) ) {
4563     switch(status_bit) {
4564     case 'z':
4565       emitSKPNZ;
4566       break;
4567
4568     case 'c':
4569       emitSKPNC;
4570       break;
4571
4572     case 'd':
4573       emitSKPDC;
4574       break;
4575
4576     }
4577
4578     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4579     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4580
4581   } else {
4582
4583     switch(status_bit) {
4584
4585     case 'z':
4586       emitSKPZ;
4587       break;
4588
4589     case 'c':
4590       emitSKPC;
4591       break;
4592
4593     case 'd':
4594       emitSKPDC;
4595       break;
4596     }
4597     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4598     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4599
4600   }
4601
4602 }
4603 #endif
4604
4605 /*-----------------------------------------------------------------*/
4606 /* genSkipc                                                        */
4607 /*-----------------------------------------------------------------*/
4608 static void genSkipc(resolvedIfx *rifx)
4609 {
4610   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4611   
4612   if(!rifx)
4613     return;
4614
4615   if(rifx->condition)
4616     emitSKPC;
4617   else
4618     emitSKPNC;
4619
4620   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4621   rifx->generated = 1;
4622 }
4623
4624 /*-----------------------------------------------------------------*/
4625 /* genSkipz2                                                       */
4626 /*-----------------------------------------------------------------*/
4627 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4628 {
4629   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4630   
4631   if(!rifx)
4632     return;
4633
4634   if( (rifx->condition ^ invert_condition) & 1)
4635     emitSKPZ;
4636   else
4637     emitSKPNZ;
4638
4639   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4640   rifx->generated = 1;
4641 }
4642
4643 #if 0
4644 /*-----------------------------------------------------------------*/
4645 /* genSkipz                                                        */
4646 /*-----------------------------------------------------------------*/
4647 static void genSkipz(iCode *ifx, int condition)
4648 {
4649   if(!ifx)
4650     return;
4651
4652   if(condition)
4653     emitSKPNZ;
4654   else
4655     emitSKPZ;
4656
4657   if ( IC_TRUE(ifx) )
4658     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4659   else
4660     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4661
4662   if ( IC_TRUE(ifx) )
4663     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4664   else
4665     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4666
4667 }
4668 #endif
4669
4670 /*-----------------------------------------------------------------*/
4671 /* genSkipCond                                                     */
4672 /*-----------------------------------------------------------------*/
4673 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4674 {
4675   if(!rifx)
4676     return;
4677
4678   if(rifx->condition)
4679     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4680   else
4681     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4682
4683
4684   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4685   rifx->generated = 1;
4686 }
4687
4688 #if 0
4689 /*-----------------------------------------------------------------*/
4690 /* genChkZeroes :- greater or less than comparison                 */
4691 /*     For each byte in a literal that is zero, inclusive or the   */
4692 /*     the corresponding byte in the operand with W                */
4693 /*     returns true if any of the bytes are zero                   */
4694 /*-----------------------------------------------------------------*/
4695 static int genChkZeroes(operand *op, int lit,  int size)
4696 {
4697
4698   int i;
4699   int flag =1;
4700
4701   while(size--) {
4702     i = (lit >> (size*8)) & 0xff;
4703
4704     if(i==0) {
4705       if(flag) 
4706         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4707       else
4708         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4709       flag = 0;
4710     }
4711   }
4712
4713   return (flag==0);
4714 }
4715 #endif
4716
4717 /*-----------------------------------------------------------------*/
4718 /* genCmp :- greater or less than comparison                       */
4719 /*-----------------------------------------------------------------*/
4720 static void genCmp (operand *left,operand *right,
4721                     operand *result, iCode *ifx, int sign)
4722 {
4723   int size; //, offset = 0 ;
4724   unsigned long lit = 0L,i = 0;
4725   resolvedIfx rFalseIfx;
4726   //  resolvedIfx rTrueIfx;
4727   symbol *truelbl;
4728   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4729 /*
4730   if(ifx) {
4731     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4732     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4733   }
4734 */
4735
4736   resolveIfx(&rFalseIfx,ifx);
4737   truelbl  = newiTempLabel(NULL);
4738   size = max(AOP_SIZE(left),AOP_SIZE(right));
4739
4740   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4741
4742 #define _swapp
4743
4744   /* if literal is on the right then swap with left */
4745   if ((AOP_TYPE(right) == AOP_LIT)) {
4746     operand *tmp = right ;
4747     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4748     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4749 #ifdef _swapp
4750
4751     lit = (lit - 1) & mask;
4752     right = left;
4753     left = tmp;
4754     rFalseIfx.condition ^= 1;
4755 #endif
4756
4757   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4758     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4759   }
4760
4761
4762   //if(IC_TRUE(ifx) == NULL)
4763   /* if left & right are bit variables */
4764   if (AOP_TYPE(left) == AOP_CRY &&
4765       AOP_TYPE(right) == AOP_CRY ) {
4766     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4767     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4768   } else {
4769     /* subtract right from left if at the
4770        end the carry flag is set then we know that
4771        left is greater than right */
4772
4773     symbol *lbl  = newiTempLabel(NULL);
4774
4775 #if 0
4776         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4777                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
4778 #endif
4779
4780 #ifndef _swapp
4781     if(AOP_TYPE(right) == AOP_LIT) {
4782
4783       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4784
4785       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4786
4787       /* special cases */
4788
4789       if(lit == 0) {
4790
4791         if(sign != 0) 
4792           genSkipCond(&rFalseIfx,left,size-1,7);
4793         else 
4794           /* no need to compare to 0...*/
4795           /* NOTE: this is a de-generate compare that most certainly 
4796            *       creates some dead code. */
4797           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4798
4799         if(ifx) ifx->generated = 1;
4800         return;
4801
4802       }
4803       size--;
4804
4805       if(size == 0) {
4806         //i = (lit >> (size*8)) & 0xff;
4807         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4808         
4809         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4810
4811         i = ((0-lit) & 0xff);
4812         if(sign) {
4813           if( i == 0x81) { 
4814             /* lit is 0x7f, all signed chars are less than
4815              * this except for 0x7f itself */
4816             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4817             genSkipz2(&rFalseIfx,0);
4818           } else {
4819             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4820             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4821             genSkipc(&rFalseIfx);
4822           }
4823
4824         } else {
4825           if(lit == 1) {
4826             genSkipz2(&rFalseIfx,1);
4827           } else {
4828             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4829             genSkipc(&rFalseIfx);
4830           }
4831         }
4832
4833         if(ifx) ifx->generated = 1;
4834         return;
4835       }
4836
4837       /* chars are out of the way. now do ints and longs */
4838
4839
4840       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4841         
4842       /* special cases */
4843
4844       if(sign) {
4845
4846         if(lit == 0) {
4847           genSkipCond(&rFalseIfx,left,size,7);
4848           if(ifx) ifx->generated = 1;
4849           return;
4850         }
4851
4852         if(lit <0x100) {
4853           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4854
4855           //rFalseIfx.condition ^= 1;
4856           //genSkipCond(&rFalseIfx,left,size,7);
4857           //rFalseIfx.condition ^= 1;
4858
4859           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4860           if(rFalseIfx.condition)
4861             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4862           else
4863             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4864
4865           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4866           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4867           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4868
4869           while(size > 1)
4870             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4871
4872           if(rFalseIfx.condition) {
4873             emitSKPZ;
4874             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4875
4876           } else {
4877             emitSKPNZ;
4878           }
4879
4880           genSkipc(&rFalseIfx);
4881           pic16_emitpLabel(truelbl->key);
4882           if(ifx) ifx->generated = 1;
4883           return;
4884
4885         }
4886
4887         if(size == 1) {
4888
4889           if( (lit & 0xff) == 0) {
4890             /* lower byte is zero */
4891             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4892             i = ((lit >> 8) & 0xff) ^0x80;
4893             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4894             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4895             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4896             genSkipc(&rFalseIfx);
4897
4898
4899             if(ifx) ifx->generated = 1;
4900             return;
4901
4902           }
4903         } else {
4904           /* Special cases for signed longs */
4905           if( (lit & 0xffffff) == 0) {
4906             /* lower byte is zero */
4907             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4908             i = ((lit >> 8*3) & 0xff) ^0x80;
4909             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4910             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4911             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4912             genSkipc(&rFalseIfx);
4913
4914
4915             if(ifx) ifx->generated = 1;
4916             return;
4917
4918           }
4919
4920         }
4921
4922
4923         if(lit & (0x80 << (size*8))) {
4924           /* lit is negative */
4925           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4926
4927           //genSkipCond(&rFalseIfx,left,size,7);
4928
4929           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4930
4931           if(rFalseIfx.condition)
4932             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4933           else
4934             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4935
4936
4937         } else {
4938           /* lit is positive */
4939           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4940           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4941           if(rFalseIfx.condition)
4942             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4943           else
4944             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4945
4946         }
4947
4948         /*
4949           This works, but is only good for ints.
4950           It also requires a "known zero" register.
4951           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4952           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4953           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4954           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4955           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4956           genSkipc(&rFalseIfx);
4957
4958           pic16_emitpLabel(truelbl->key);
4959           if(ifx) ifx->generated = 1;
4960           return;
4961         **/
4962           
4963         /* There are no more special cases, so perform a general compare */
4964   
4965         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4966         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4967
4968         while(size--) {
4969
4970           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4971           emitSKPNZ;
4972           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4973         }
4974         //rFalseIfx.condition ^= 1;
4975         genSkipc(&rFalseIfx);
4976
4977         pic16_emitpLabel(truelbl->key);
4978
4979         if(ifx) ifx->generated = 1;
4980         return;
4981
4982
4983       }
4984
4985
4986       /* sign is out of the way. So now do an unsigned compare */
4987       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4988
4989
4990       /* General case - compare to an unsigned literal on the right.*/
4991
4992       i = (lit >> (size*8)) & 0xff;
4993       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4994       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4995       while(size--) {
4996         i = (lit >> (size*8)) & 0xff;
4997
4998         if(i) {
4999           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5000           emitSKPNZ;
5001           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5002         } else {
5003           /* this byte of the lit is zero, 
5004            *if it's not the last then OR in the variable */
5005           if(size)
5006             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5007         }
5008       }
5009
5010
5011       pic16_emitpLabel(lbl->key);
5012 //      pic16_emitpLabel(truelbl->key);
5013       //if(emitFinalCheck)
5014       genSkipc(&rFalseIfx);
5015       if(sign)
5016         pic16_emitpLabel(truelbl->key);
5017
5018       if(ifx) ifx->generated = 1;
5019       return;
5020
5021
5022     }
5023 #endif  // _swapp
5024
5025     if(AOP_TYPE(left) == AOP_LIT) {
5026       //symbol *lbl = newiTempLabel(NULL);
5027
5028       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5029
5030
5031       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5032
5033       /* Special cases */
5034       if((lit == 0) && (sign == 0)){
5035
5036         size--;
5037         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5038         while(size) 
5039           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5040
5041         genSkipz2(&rFalseIfx,0);
5042         if(ifx) ifx->generated = 1;
5043         return;
5044       }
5045
5046       if(size==1) {
5047         /* Special cases */
5048         lit &= 0xff;
5049         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5050           /* degenerate compare can never be true */
5051           if(rFalseIfx.condition == 0)
5052             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5053
5054           if(ifx) ifx->generated = 1;
5055           return;
5056         }
5057
5058         if(sign) {
5059           /* signed comparisons to a literal byte */
5060
5061           int lp1 = (lit+1) & 0xff;
5062
5063           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5064           switch (lp1) {
5065           case 0:
5066             rFalseIfx.condition ^= 1;
5067             genSkipCond(&rFalseIfx,right,0,7);
5068             break;
5069           case 0x7f:
5070             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5071             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5072             genSkipz2(&rFalseIfx,1);
5073             break;
5074           default:
5075             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5076             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5077             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5078             rFalseIfx.condition ^= 1;
5079             genSkipc(&rFalseIfx);
5080             break;
5081           }
5082         } else {
5083           /* unsigned comparisons to a literal byte */
5084
5085           switch(lit & 0xff ) {
5086           case 0:
5087             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5088             genSkipz2(&rFalseIfx,0);
5089             break;
5090           case 0x7f:
5091             rFalseIfx.condition ^= 1;
5092             genSkipCond(&rFalseIfx,right,0,7);
5093             break;
5094
5095           default:
5096             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5097             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5098             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5099             rFalseIfx.condition ^= 1;
5100             if (AOP_TYPE(result) == AOP_CRY)
5101               genSkipc(&rFalseIfx);
5102             else {
5103               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5104               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5105             }         
5106             break;
5107           }
5108         }
5109
5110         if(ifx) ifx->generated = 1;
5111         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5112                 goto check_carry;
5113         return;
5114
5115       } else {
5116
5117         /* Size is greater than 1 */
5118
5119         if(sign) {
5120           int lp1 = lit+1;
5121
5122           size--;
5123
5124           if(lp1 == 0) {
5125             /* this means lit = 0xffffffff, or -1 */
5126
5127
5128             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5129             rFalseIfx.condition ^= 1;
5130             genSkipCond(&rFalseIfx,right,size,7);
5131             if(ifx) ifx->generated = 1;
5132             return;
5133           }
5134
5135           if(lit == 0) {
5136             int s = size;
5137
5138             if(rFalseIfx.condition) {
5139               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5140               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5141             }
5142
5143             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5144             while(size--)
5145               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5146
5147
5148             emitSKPZ;
5149             if(rFalseIfx.condition) {
5150               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5151               pic16_emitpLabel(truelbl->key);
5152             }else {
5153               rFalseIfx.condition ^= 1;
5154               genSkipCond(&rFalseIfx,right,s,7);
5155             }
5156
5157             if(ifx) ifx->generated = 1;
5158             return;
5159           }
5160
5161           if((size == 1) &&  (0 == (lp1&0xff))) {
5162             /* lower byte of signed word is zero */
5163             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5164             i = ((lp1 >> 8) & 0xff) ^0x80;
5165             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5166             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5167             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5168             rFalseIfx.condition ^= 1;
5169             genSkipc(&rFalseIfx);
5170
5171
5172             if(ifx) ifx->generated = 1;
5173             return;
5174           }
5175
5176           if(lit & (0x80 << (size*8))) {
5177             /* Lit is less than zero */
5178             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5179             //rFalseIfx.condition ^= 1;
5180             //genSkipCond(&rFalseIfx,left,size,7);
5181             //rFalseIfx.condition ^= 1;
5182             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5183             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5184
5185             if(rFalseIfx.condition)
5186               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5187             else
5188               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5189
5190
5191           } else {
5192             /* Lit is greater than or equal to zero */
5193             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5194             //rFalseIfx.condition ^= 1;
5195             //genSkipCond(&rFalseIfx,right,size,7);
5196             //rFalseIfx.condition ^= 1;
5197
5198             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5199             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5200
5201             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5202             if(rFalseIfx.condition)
5203               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5204             else
5205               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5206
5207           }
5208
5209
5210           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5211           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5212
5213           while(size--) {
5214
5215             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5216             emitSKPNZ;
5217             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5218           }
5219           rFalseIfx.condition ^= 1;
5220           //rFalseIfx.condition = 1;
5221           genSkipc(&rFalseIfx);
5222
5223           pic16_emitpLabel(truelbl->key);
5224
5225           if(ifx) ifx->generated = 1;
5226           return;
5227           // end of if (sign)
5228         } else {
5229
5230           /* compare word or long to an unsigned literal on the right.*/
5231
5232
5233           size--;
5234           if(lit < 0xff) {
5235             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5236             switch (lit) {
5237             case 0:
5238               break; /* handled above */
5239 /*
5240             case 0xff:
5241               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5242               while(size--)
5243                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5244               genSkipz2(&rFalseIfx,0);
5245               break;
5246 */
5247             default:
5248               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5249               while(--size)
5250                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5251
5252               emitSKPZ;
5253               if(rFalseIfx.condition)
5254                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5255               else
5256                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5257
5258
5259               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5260               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5261
5262               rFalseIfx.condition ^= 1;
5263               genSkipc(&rFalseIfx);
5264             }
5265
5266             pic16_emitpLabel(truelbl->key);
5267
5268             if(ifx) ifx->generated = 1;
5269             return;
5270           }
5271
5272
5273           lit++;
5274           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5275           i = (lit >> (size*8)) & 0xff;
5276
5277           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5278           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5279
5280           while(size--) {
5281             i = (lit >> (size*8)) & 0xff;
5282
5283             if(i) {
5284               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5285               emitSKPNZ;
5286               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5287             } else {
5288               /* this byte of the lit is zero, 
5289                * if it's not the last then OR in the variable */
5290               if(size)
5291                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5292             }
5293           }
5294
5295
5296           pic16_emitpLabel(lbl->key);
5297
5298           rFalseIfx.condition ^= 1;
5299
5300           genSkipc(&rFalseIfx);
5301         }
5302
5303         if(sign)
5304           pic16_emitpLabel(truelbl->key);
5305         if(ifx) ifx->generated = 1;
5306         return;
5307       }
5308     }
5309     /* Compare two variables */
5310
5311     DEBUGpic16_emitcode(";sign","%d",sign);
5312
5313     size--;
5314     if(sign) {
5315       /* Sigh. thus sucks... */
5316       if(size) {
5317         pCodeOp *pctemp;
5318         
5319         pctemp = pic16_popGetTempReg();
5320         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5321         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5322         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5323         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5324         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5325         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5326         pic16_popReleaseTempReg(pctemp);
5327       } else {
5328         /* Signed char comparison */
5329         /* Special thanks to Nikolai Golovchenko for this snippet */
5330         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5331         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5332         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5333         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5334         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5335         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5336
5337         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5338         genSkipc(&rFalseIfx);
5339           
5340         if(ifx) ifx->generated = 1;
5341         return;
5342       }
5343
5344     } else {
5345
5346       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5347       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5348     }
5349
5350
5351     /* The rest of the bytes of a multi-byte compare */
5352     while (size) {
5353
5354       emitSKPZ;
5355       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5356       size--;
5357
5358       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5359       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5360
5361
5362     }
5363
5364     pic16_emitpLabel(lbl->key);
5365
5366     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5367     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5368         (AOP_TYPE(result) == AOP_REG)) {
5369       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5370       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5371     } else {
5372       genSkipc(&rFalseIfx);
5373     }         
5374     //genSkipc(&rFalseIfx);
5375     if(ifx) ifx->generated = 1;
5376
5377     return;
5378
5379   }
5380
5381 check_carry:
5382   if ((AOP_TYPE(result) != AOP_CRY) 
5383         && AOP_SIZE(result)) {
5384     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5385
5386     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5387
5388     pic16_outBitC(result);
5389   } else {
5390     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5391     /* if the result is used in the next
5392        ifx conditional branch then generate
5393        code a little differently */
5394     if (ifx )
5395       genIfxJump (ifx,"c");
5396     else
5397       pic16_outBitC(result);
5398     /* leave the result in acc */
5399   }
5400
5401 }
5402
5403 /*-----------------------------------------------------------------*/
5404 /* genCmpGt :- greater than comparison                             */
5405 /*-----------------------------------------------------------------*/
5406 static void genCmpGt (iCode *ic, iCode *ifx)
5407 {
5408     operand *left, *right, *result;
5409     sym_link *letype , *retype;
5410     int sign ;
5411
5412     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5413     left = IC_LEFT(ic);
5414     right= IC_RIGHT(ic);
5415     result = IC_RESULT(ic);
5416
5417     letype = getSpec(operandType(left));
5418     retype =getSpec(operandType(right));
5419     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5420     /* assign the amsops */
5421     pic16_aopOp (left,ic,FALSE);
5422     pic16_aopOp (right,ic,FALSE);
5423     pic16_aopOp (result,ic,TRUE);
5424
5425     genCmp(right, left, result, ifx, sign);
5426
5427     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5428     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5429     pic16_freeAsmop(result,NULL,ic,TRUE); 
5430 }
5431
5432 /*-----------------------------------------------------------------*/
5433 /* genCmpLt - less than comparisons                                */
5434 /*-----------------------------------------------------------------*/
5435 static void genCmpLt (iCode *ic, iCode *ifx)
5436 {
5437     operand *left, *right, *result;
5438     sym_link *letype , *retype;
5439     int sign ;
5440
5441     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5442     left = IC_LEFT(ic);
5443     right= IC_RIGHT(ic);
5444     result = IC_RESULT(ic);
5445
5446     letype = getSpec(operandType(left));
5447     retype =getSpec(operandType(right));
5448     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5449
5450     /* assign the amsops */
5451     pic16_aopOp (left,ic,FALSE);
5452     pic16_aopOp (right,ic,FALSE);
5453     pic16_aopOp (result,ic,TRUE);
5454
5455     genCmp(left, right, result, ifx, sign);
5456
5457     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5458     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5459     pic16_freeAsmop(result,NULL,ic,TRUE); 
5460 }
5461
5462 #if 0
5463 // not needed ATM
5464 // FIXME reenable literal optimisation when the pic16 port is stable
5465
5466 /*-----------------------------------------------------------------*/
5467 /* genc16bit2lit - compare a 16 bit value to a literal             */
5468 /*-----------------------------------------------------------------*/
5469 static void genc16bit2lit(operand *op, int lit, int offset)
5470 {
5471   int i;
5472
5473   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
5474   if( (lit&0xff) == 0) 
5475     i=1;
5476   else
5477     i=0;
5478
5479   switch( BYTEofLONG(lit,i)) { 
5480   case 0:
5481     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5482     break;
5483   case 1:
5484     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5485     break;
5486   case 0xff:
5487     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5488     break;
5489   default:
5490     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5491     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5492   }
5493
5494   i ^= 1;
5495
5496   switch( BYTEofLONG(lit,i)) { 
5497   case 0:
5498     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5499     break;
5500   case 1:
5501     emitSKPNZ;
5502     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5503     break;
5504   case 0xff:
5505     emitSKPNZ;
5506     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5507     break;
5508   default:
5509     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5510     emitSKPNZ;
5511     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5512
5513   }
5514
5515 }
5516 #endif
5517
5518 #if 0
5519 // not needed ATM
5520 /*-----------------------------------------------------------------*/
5521 /* gencjneshort - compare and jump if not equal                    */
5522 /*-----------------------------------------------------------------*/
5523 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5524 {
5525   int size = max(AOP_SIZE(left),AOP_SIZE(right));
5526   int offset = 0;
5527   int res_offset = 0;  /* the result may be a different size then left or right */
5528   int res_size = AOP_SIZE(result);
5529   resolvedIfx rIfx;
5530   symbol *lbl, *lbl_done;
5531
5532   unsigned long lit = 0L;
5533   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5534
5535   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5536   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5537   if(result)
5538     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
5539   resolveIfx(&rIfx,ifx);
5540   lbl =  newiTempLabel(NULL);
5541   lbl_done =  newiTempLabel(NULL);
5542
5543
5544   /* if the left side is a literal or 
5545      if the right is in a pointer register and left 
5546      is not */
5547   if ((AOP_TYPE(left) == AOP_LIT) || 
5548       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5549     operand *t = right;
5550     right = left;
5551     left = t;
5552   }
5553   if(AOP_TYPE(right) == AOP_LIT)
5554     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5555
5556   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5557     preserve_result = 1;
5558
5559   if(result && !preserve_result)
5560     {
5561       int i;
5562       for(i = 0; i < AOP_SIZE(result); i++)
5563         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5564     }
5565
5566
5567   /* if the right side is a literal then anything goes */
5568   if (AOP_TYPE(right) == AOP_LIT &&
5569       AOP_TYPE(left) != AOP_DIR ) {
5570     switch(size) {
5571     case 2:
5572       genc16bit2lit(left, lit, 0);
5573       emitSKPZ;
5574       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5575       break;
5576     default:
5577       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5578       while (size--) {
5579         if(lit & 0xff) {
5580           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5581           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5582         } else {
5583           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5584         }
5585
5586         emitSKPZ;
5587         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5588         offset++;
5589         if(res_offset < res_size-1)
5590           res_offset++;
5591         lit >>= 8;
5592       }
5593       break;
5594     }
5595   }
5596
5597   /* if the right side is in a register or in direct space or
5598      if the left is a pointer register & right is not */    
5599   else if (AOP_TYPE(right) == AOP_REG ||
5600            AOP_TYPE(right) == AOP_DIR || 
5601            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5602            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5603     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5604     int lbl_key = lbl->key;
5605
5606     if(result) {
5607       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5608       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5609     }else {
5610       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5611       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5612               __FUNCTION__,__LINE__);
5613       return;
5614     }
5615    
5616 /*     switch(size) { */
5617 /*     case 2: */
5618 /*       genc16bit2lit(left, lit, 0); */
5619 /*       emitSKPNZ; */
5620 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5621 /*       break; */
5622 /*     default: */
5623     while (size--) {
5624       int emit_skip=1;
5625       if((AOP_TYPE(left) == AOP_DIR) && 
5626          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5627
5628         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5629         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5630
5631       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5632             
5633         switch (lit & 0xff) {
5634         case 0:
5635           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5636           break;
5637         case 1:
5638           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5639           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5640           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5641           emit_skip=0;
5642           break;
5643         case 0xff:
5644           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5645           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5646           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5647           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5648           emit_skip=0;
5649           break;
5650         default:
5651           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5652           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5653         }
5654         lit >>= 8;
5655
5656       } else {
5657         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5658       }
5659       if(emit_skip) {
5660         if(AOP_TYPE(result) == AOP_CRY) {
5661           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5662           if(rIfx.condition)
5663             emitSKPNZ;
5664           else
5665             emitSKPZ;
5666           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5667         } else {
5668           /* fix me. probably need to check result size too */
5669           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5670           if(rIfx.condition)
5671             emitSKPZ;
5672           else
5673             emitSKPNZ;
5674           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5675           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5676         }
5677         if(ifx)
5678           ifx->generated=1;
5679       }
5680       emit_skip++;
5681       offset++;
5682       if(res_offset < res_size-1)
5683         res_offset++;
5684     }
5685 /*       break; */
5686 /*     } */
5687   } else if(AOP_TYPE(right) == AOP_REG &&
5688             AOP_TYPE(left) != AOP_DIR){
5689
5690     while(size--) {
5691       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5692       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5693       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5694       if(rIfx.condition)
5695         emitSKPNZ;
5696       else
5697         emitSKPZ;
5698       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5699       offset++;
5700       if(res_offset < res_size-1)
5701         res_offset++;
5702     }
5703       
5704   }else{
5705     /* right is a pointer reg need both a & b */
5706     while(size--) {
5707       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5708       if(strcmp(l,"b"))
5709         pic16_emitcode("mov","b,%s",l);
5710       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5711       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5712       offset++;
5713     }
5714   }
5715
5716   if(result && preserve_result)
5717     {
5718       int i;
5719       for(i = 0; i < AOP_SIZE(result); i++)
5720         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5721     }
5722
5723   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5724
5725   if(result && preserve_result)
5726     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5727
5728   if(!rIfx.condition)
5729     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5730
5731   pic16_emitpLabel(lbl->key);
5732
5733   if(result && preserve_result)
5734     {
5735       int i;
5736       for(i = 0; i < AOP_SIZE(result); i++)
5737         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5738
5739       pic16_emitpLabel(lbl_done->key);
5740    }
5741
5742   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5743
5744   if(ifx)
5745     ifx->generated = 1;
5746 }
5747 #endif
5748
5749 #if 0
5750 /*-----------------------------------------------------------------*/
5751 /* gencjne - compare and jump if not equal                         */
5752 /*-----------------------------------------------------------------*/
5753 static void gencjne(operand *left, operand *right, iCode *ifx)
5754 {
5755     symbol *tlbl  = newiTempLabel(NULL);
5756
5757     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5758     gencjneshort(left, right, lbl);
5759
5760     pic16_emitcode("mov","a,%s",one);
5761     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5762     pic16_emitcode("","%05d_DS_:",lbl->key+100);
5763     pic16_emitcode("clr","a");
5764     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5765
5766     pic16_emitpLabel(lbl->key);
5767     pic16_emitpLabel(tlbl->key);
5768
5769 }
5770 #endif
5771
5772
5773 /*-----------------------------------------------------------------*/
5774 /* is_LitOp - check if operand has to be treated as literal        */
5775 /*-----------------------------------------------------------------*/
5776 static bool is_LitOp(operand *op)
5777 {
5778   return (AOP_TYPE(op) == AOP_LIT)
5779       || ( (AOP_TYPE(op) == AOP_PCODE)
5780           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5781               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));  
5782 }
5783
5784 /*-----------------------------------------------------------------*/
5785 /* is_LitAOp - check if operand has to be treated as literal        */
5786 /*-----------------------------------------------------------------*/
5787 static bool is_LitAOp(asmop *aop)
5788 {
5789   return (aop->type == AOP_LIT)
5790       || ( (aop->type == AOP_PCODE)
5791           && ( (aop->aopu.pcop->type == PO_LITERAL)
5792               || (aop->aopu.pcop->type == PO_IMMEDIATE) ));  
5793 }
5794
5795
5796
5797 /*-----------------------------------------------------------------*/
5798 /* genCmpEq - generates code for equal to                          */
5799 /*-----------------------------------------------------------------*/
5800 static void genCmpEq (iCode *ic, iCode *ifx)
5801 {
5802   operand *left, *right, *result;
5803   symbol *falselbl = newiTempLabel(NULL);
5804   symbol *donelbl = newiTempLabel(NULL);
5805
5806   int preserve_result = 0;
5807   int generate_result = 0;
5808   int i=0;
5809
5810   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5811   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5812   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5813  
5814   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5815   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5816
5817   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5818     {
5819       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5820       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5821       goto release;
5822     }
5823
5824   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5825     {
5826       operand *tmp = right ;
5827       right = left;
5828       left = tmp;
5829     }
5830
5831   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5832     preserve_result = 1;
5833
5834   if(result && AOP_SIZE(result))
5835     generate_result = 1;
5836
5837   if(generate_result && !preserve_result)
5838     {
5839       for(i = 0; i < AOP_SIZE(result); i++)
5840         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5841     }
5842
5843   for(i=0; i < AOP_SIZE(left); i++)
5844     {
5845       if(AOP_TYPE(left) != AOP_ACC)
5846         {
5847           if(is_LitOp(left))
5848             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5849           else
5850             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5851         }
5852       if(is_LitOp(right))
5853         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
5854       else
5855         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
5856
5857       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5858     }
5859
5860   // result == true
5861
5862   if(generate_result && preserve_result)
5863     {
5864       for(i = 0; i < AOP_SIZE(result); i++)
5865         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5866     }
5867
5868   if(generate_result)
5869     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5870
5871   if(generate_result && preserve_result)
5872     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5873
5874   if(ifx && IC_TRUE(ifx))
5875     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5876
5877   if(ifx && IC_FALSE(ifx))
5878     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5879
5880   pic16_emitpLabel(falselbl->key);
5881
5882   // result == false
5883
5884   if(ifx && IC_FALSE(ifx))
5885     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5886
5887   if(generate_result && preserve_result)
5888     {
5889       for(i = 0; i < AOP_SIZE(result); i++)
5890         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5891     }
5892
5893   pic16_emitpLabel(donelbl->key);
5894
5895   if(ifx)
5896     ifx->generated = 1;
5897
5898 release:
5899   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5900   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5901   pic16_freeAsmop(result,NULL,ic,TRUE);
5902
5903 }
5904
5905
5906 #if 0
5907 // old version kept for reference
5908
5909 /*-----------------------------------------------------------------*/
5910 /* genCmpEq - generates code for equal to                          */
5911 /*-----------------------------------------------------------------*/
5912 static void genCmpEq (iCode *ic, iCode *ifx)
5913 {
5914     operand *left, *right, *result;
5915     unsigned long lit = 0L;
5916     int size,offset=0;
5917     symbol *falselbl  = newiTempLabel(NULL);
5918
5919
5920     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5921
5922     if(ifx)
5923       DEBUGpic16_emitcode ("; ifx is non-null","");
5924     else
5925       DEBUGpic16_emitcode ("; ifx is null","");
5926
5927     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5928     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5929     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5930
5931     size = max(AOP_SIZE(left),AOP_SIZE(right));
5932
5933     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5934
5935     /* if literal, literal on the right or 
5936     if the right is in a pointer register and left 
5937     is not */
5938     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
5939         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5940       operand *tmp = right ;
5941       right = left;
5942       left = tmp;
5943     }
5944
5945
5946     if(ifx && !AOP_SIZE(result)){
5947         symbol *tlbl;
5948         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
5949         /* if they are both bit variables */
5950         if (AOP_TYPE(left) == AOP_CRY &&
5951             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5952                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
5953             if(AOP_TYPE(right) == AOP_LIT){
5954                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5955                 if(lit == 0L){
5956                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5957                     pic16_emitcode("cpl","c");
5958                 } else if(lit == 1L) {
5959                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5960                 } else {
5961                     pic16_emitcode("clr","c");
5962                 }
5963                 /* AOP_TYPE(right) == AOP_CRY */
5964             } else {
5965                 symbol *lbl = newiTempLabel(NULL);
5966                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5967                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5968                 pic16_emitcode("cpl","c");
5969                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5970             }
5971             /* if true label then we jump if condition
5972             supplied is true */
5973             tlbl = newiTempLabel(NULL);
5974             if ( IC_TRUE(ifx) ) {
5975                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5976                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5977             } else {
5978                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5979                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5980             }
5981             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5982
5983                 {
5984                 /* left and right are both bit variables, result is carry */
5985                         resolvedIfx rIfx;
5986               
5987                         resolveIfx(&rIfx,ifx);
5988
5989                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5990                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5991                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5992                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5993                         genSkipz2(&rIfx,0);
5994                 }
5995         } else {
5996
5997                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
5998
5999                         /* They're not both bit variables. Is the right a literal? */
6000                         if(AOP_TYPE(right) == AOP_LIT) {
6001                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6002             
6003                         switch(size) {
6004
6005                                 case 1:
6006                                         switch(lit & 0xff) {
6007                                                 case 1:
6008                                                                 if ( IC_TRUE(ifx) ) {
6009                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6010                                                                         emitSKPNZ;
6011                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6012                                                                 } else {
6013                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6014                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6015                                                                 }
6016                                                                 break;
6017                                                 case 0xff:
6018                                                                 if ( IC_TRUE(ifx) ) {
6019                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6020                                                                         emitSKPNZ;
6021                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6022                                                                 } else {
6023                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6024                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6025                                                                 }
6026                                                                 break;
6027                                                 default:
6028                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6029                                                                 if(lit)
6030                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6031                                                                 genSkip(ifx,'z');
6032                                         } // switch lit
6033
6034
6035                                         /* end of size == 1 */
6036                                         break;
6037               
6038                                 case 2:
6039                                         genc16bit2lit(left,lit,offset);
6040                                         genSkip(ifx,'z');
6041                                         break;
6042                                         /* end of size == 2 */
6043
6044                                 default:
6045                                         /* size is 4 */
6046                                         if(lit==0) {
6047                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6048                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6049                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6050                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6051                                                 genSkip(ifx,'z');
6052                                         } else {
6053                                                 /* search for patterns that can be optimized */
6054
6055                                                 genc16bit2lit(left,lit,0);
6056                                                 lit >>= 16;
6057                                                 if(lit) {
6058                                                                 if(IC_TRUE(ifx))
6059                                                                 emitSKPZ; // if hi word unequal
6060                                                                 else
6061                                                                 emitSKPNZ; // if hi word equal
6062                                                                 // fail early
6063                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6064                                                         genc16bit2lit(left,lit,2);
6065                                                         genSkip(ifx,'z');
6066                                                 } else {
6067                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6068                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6069                                                         genSkip(ifx,'z');
6070                                                 }
6071                                         }
6072                                                 pic16_emitpLabel(falselbl->key);
6073                                                 break;
6074
6075                         } // switch size
6076           
6077                         ifx->generated = 1;
6078                         goto release ;
6079             
6080
6081           } else if(AOP_TYPE(right) == AOP_CRY ) {
6082             /* we know the left is not a bit, but that the right is */
6083             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6084             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6085                       pic16_popGet(AOP(right),offset));
6086             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6087
6088             /* if the two are equal, then W will be 0 and the Z bit is set
6089              * we could test Z now, or go ahead and check the high order bytes if
6090              * the variable we're comparing is larger than a byte. */
6091
6092             while(--size)
6093               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6094
6095             if ( IC_TRUE(ifx) ) {
6096               emitSKPNZ;
6097               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6098               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6099             } else {
6100               emitSKPZ;
6101               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6102               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6103             }
6104
6105           } else {
6106             /* They're both variables that are larger than bits */
6107             int s = size;
6108
6109             tlbl = newiTempLabel(NULL);
6110
6111             while(size--) {
6112               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6113               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6114
6115               if ( IC_TRUE(ifx) ) {
6116                 if(size) {
6117                   emitSKPZ;
6118                 
6119                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6120
6121                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6122                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6123                 } else {
6124                   emitSKPNZ;
6125
6126                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6127
6128
6129                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6130                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6131                 }
6132               } else {
6133                 emitSKPZ;
6134
6135                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6136
6137                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6138                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6139               }
6140               offset++;
6141             }
6142             if(s>1 && IC_TRUE(ifx)) {
6143               pic16_emitpLabel(tlbl->key);
6144               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
6145             }
6146           }
6147         }
6148         /* mark the icode as generated */
6149         ifx->generated = 1;
6150         goto release ;
6151     }
6152
6153     /* if they are both bit variables */
6154     if (AOP_TYPE(left) == AOP_CRY &&
6155         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6156         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
6157         if(AOP_TYPE(right) == AOP_LIT){
6158             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6159             if(lit == 0L){
6160                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6161                 pic16_emitcode("cpl","c");
6162             } else if(lit == 1L) {
6163                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6164             } else {
6165                 pic16_emitcode("clr","c");
6166             }
6167             /* AOP_TYPE(right) == AOP_CRY */
6168         } else {
6169             symbol *lbl = newiTempLabel(NULL);
6170             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6171             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6172             pic16_emitcode("cpl","c");
6173             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6174         }
6175         /* c = 1 if egal */
6176         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6177             pic16_outBitC(result);
6178             goto release ;
6179         }
6180         if (ifx) {
6181             genIfxJump (ifx,"c");
6182             goto release ;
6183         }
6184         /* if the result is used in an arithmetic operation
6185         then put the result in place */
6186         pic16_outBitC(result);
6187     } else {
6188       
6189       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
6190       gencjne(left,right,result,ifx);
6191 /*
6192       if(ifx) 
6193         gencjne(left,right,newiTempLabel(NULL));
6194       else {
6195         if(IC_TRUE(ifx)->key)
6196           gencjne(left,right,IC_TRUE(ifx)->key);
6197         else
6198           gencjne(left,right,IC_FALSE(ifx)->key);
6199         ifx->generated = 1;
6200         goto release ;
6201       }
6202       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6203         pic16_aopPut(AOP(result),"a",0);
6204         goto release ;
6205       }
6206
6207       if (ifx) {
6208         genIfxJump (ifx,"a");
6209         goto release ;
6210       }
6211 */
6212       /* if the result is used in an arithmetic operation
6213          then put the result in place */
6214 /*
6215       if (AOP_TYPE(result) != AOP_CRY) 
6216         pic16_outAcc(result);
6217 */
6218       /* leave the result in acc */
6219     }
6220
6221 release:
6222     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6223     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6224     pic16_freeAsmop(result,NULL,ic,TRUE);
6225 }
6226 #endif
6227
6228 /*-----------------------------------------------------------------*/
6229 /* ifxForOp - returns the icode containing the ifx for operand     */
6230 /*-----------------------------------------------------------------*/
6231 static iCode *ifxForOp ( operand *op, iCode *ic )
6232 {
6233     /* if true symbol then needs to be assigned */
6234     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6235     if (IS_TRUE_SYMOP(op))
6236         return NULL ;
6237
6238     /* if this has register type condition and
6239     the next instruction is ifx with the same operand
6240     and live to of the operand is upto the ifx only then */
6241     if (ic->next
6242         && ic->next->op == IFX
6243         && IC_COND(ic->next)->key == op->key
6244         && OP_SYMBOL(op)->liveTo <= ic->next->seq
6245         ) {
6246                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6247           return ic->next;
6248     }
6249
6250     if (ic->next &&
6251         ic->next->op == IFX &&
6252         IC_COND(ic->next)->key == op->key) {
6253       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6254       return ic->next;
6255     }
6256
6257     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6258     if (ic->next &&
6259         ic->next->op == IFX)
6260       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6261
6262     if (ic->next &&
6263         ic->next->op == IFX &&
6264         IC_COND(ic->next)->key == op->key) {
6265       DEBUGpic16_emitcode ("; "," key is okay");
6266       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6267                            OP_SYMBOL(op)->liveTo,
6268                            ic->next->seq);
6269     }
6270
6271 #if 0
6272     /* the code below is completely untested
6273      * it just allows ulong2fs.c compile -- VR */
6274          
6275     ic = ic->next;
6276     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6277                                         __FILE__, __FUNCTION__, __LINE__);
6278         
6279     /* if this has register type condition and
6280     the next instruction is ifx with the same operand
6281     and live to of the operand is upto the ifx only then */
6282     if (ic->next &&
6283         ic->next->op == IFX &&
6284         IC_COND(ic->next)->key == op->key &&
6285         OP_SYMBOL(op)->liveTo <= ic->next->seq )
6286         return ic->next;
6287
6288     if (ic->next &&
6289         ic->next->op == IFX &&
6290         IC_COND(ic->next)->key == op->key) {
6291       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6292       return ic->next;
6293     }
6294
6295     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6296                                         __FILE__, __FUNCTION__, __LINE__);
6297
6298 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
6299 #endif
6300
6301     return NULL;
6302 }
6303 /*-----------------------------------------------------------------*/
6304 /* genAndOp - for && operation                                     */
6305 /*-----------------------------------------------------------------*/
6306 static void genAndOp (iCode *ic)
6307 {
6308     operand *left,*right, *result;
6309 /*     symbol *tlbl; */
6310
6311     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6312     /* note here that && operations that are in an
6313     if statement are taken away by backPatchLabels
6314     only those used in arthmetic operations remain */
6315     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6316     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6317     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6318
6319     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6320
6321     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6322     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6323     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6324
6325     /* if both are bit variables */
6326 /*     if (AOP_TYPE(left) == AOP_CRY && */
6327 /*         AOP_TYPE(right) == AOP_CRY ) { */
6328 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6329 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6330 /*         pic16_outBitC(result); */
6331 /*     } else { */
6332 /*         tlbl = newiTempLabel(NULL); */
6333 /*         pic16_toBoolean(left);     */
6334 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6335 /*         pic16_toBoolean(right); */
6336 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6337 /*         pic16_outBitAcc(result); */
6338 /*     } */
6339
6340     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6341     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6342     pic16_freeAsmop(result,NULL,ic,TRUE);
6343 }
6344
6345
6346 /*-----------------------------------------------------------------*/
6347 /* genOrOp - for || operation                                      */
6348 /*-----------------------------------------------------------------*/
6349 /*
6350   tsd pic port -
6351   modified this code, but it doesn't appear to ever get called
6352 */
6353
6354 static void genOrOp (iCode *ic)
6355 {
6356     operand *left,*right, *result;
6357     symbol *tlbl;
6358
6359     /* note here that || operations that are in an
6360     if statement are taken away by backPatchLabels
6361     only those used in arthmetic operations remain */
6362     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6363     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6364     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6365     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6366
6367     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6368
6369     /* if both are bit variables */
6370     if (AOP_TYPE(left) == AOP_CRY &&
6371         AOP_TYPE(right) == AOP_CRY ) {
6372       pic16_emitcode("clrc","");
6373       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6374                AOP(left)->aopu.aop_dir,
6375                AOP(left)->aopu.aop_dir);
6376       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6377                AOP(right)->aopu.aop_dir,
6378                AOP(right)->aopu.aop_dir);
6379       pic16_emitcode("setc","");
6380
6381     } else {
6382         tlbl = newiTempLabel(NULL);
6383         pic16_toBoolean(left);
6384         emitSKPZ;
6385         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
6386         pic16_toBoolean(right);
6387         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6388
6389         pic16_outBitAcc(result);
6390     }
6391
6392     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6393     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6394     pic16_freeAsmop(result,NULL,ic,TRUE);            
6395 }
6396
6397 /*-----------------------------------------------------------------*/
6398 /* isLiteralBit - test if lit == 2^n                               */
6399 /*-----------------------------------------------------------------*/
6400 static int isLiteralBit(unsigned long lit)
6401 {
6402     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6403     0x100L,0x200L,0x400L,0x800L,
6404     0x1000L,0x2000L,0x4000L,0x8000L,
6405     0x10000L,0x20000L,0x40000L,0x80000L,
6406     0x100000L,0x200000L,0x400000L,0x800000L,
6407     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6408     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6409     int idx;
6410     
6411     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6412     for(idx = 0; idx < 32; idx++)
6413         if(lit == pw[idx])
6414             return idx+1;
6415     return 0;
6416 }
6417
6418 /*-----------------------------------------------------------------*/
6419 /* continueIfTrue -                                                */
6420 /*-----------------------------------------------------------------*/
6421 static void continueIfTrue (iCode *ic)
6422 {
6423     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6424     if(IC_TRUE(ic))
6425         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6426     ic->generated = 1;
6427 }
6428
6429 /*-----------------------------------------------------------------*/
6430 /* jmpIfTrue -                                                     */
6431 /*-----------------------------------------------------------------*/
6432 static void jumpIfTrue (iCode *ic)
6433 {
6434     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6435     if(!IC_TRUE(ic))
6436         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6437     ic->generated = 1;
6438 }
6439
6440 /*-----------------------------------------------------------------*/
6441 /* jmpTrueOrFalse -                                                */
6442 /*-----------------------------------------------------------------*/
6443 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6444 {
6445     // ugly but optimized by peephole
6446     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6447     if(IC_TRUE(ic)){
6448         symbol *nlbl = newiTempLabel(NULL);
6449         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
6450         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6451         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6452         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6453     }
6454     else{
6455         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6456         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6457     }
6458     ic->generated = 1;
6459 }
6460
6461 /*-----------------------------------------------------------------*/
6462 /* genAnd  - code for and                                          */
6463 /*-----------------------------------------------------------------*/
6464 static void genAnd (iCode *ic, iCode *ifx)
6465 {
6466   operand *left, *right, *result;
6467   int size, offset=0;  
6468   unsigned long lit = 0L;
6469   int bytelit = 0;
6470   resolvedIfx rIfx;
6471
6472
6473   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6474   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6475   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6476   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6477
6478   resolveIfx(&rIfx,ifx);
6479
6480   /* if left is a literal & right is not then exchange them */
6481   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6482       AOP_NEEDSACC(left)) {
6483     operand *tmp = right ;
6484     right = left;
6485     left = tmp;
6486   }
6487
6488   /* if result = right then exchange them */
6489   if(pic16_sameRegs(AOP(result),AOP(right))){
6490     operand *tmp = right ;
6491     right = left;
6492     left = tmp;
6493   }
6494
6495   /* if right is bit then exchange them */
6496   if (AOP_TYPE(right) == AOP_CRY &&
6497       AOP_TYPE(left) != AOP_CRY){
6498     operand *tmp = right ;
6499     right = left;
6500     left = tmp;
6501   }
6502   if(AOP_TYPE(right) == AOP_LIT)
6503     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6504
6505   size = AOP_SIZE(result);
6506
6507   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6508
6509   // if(bit & yy)
6510   // result = bit & yy;
6511   if (AOP_TYPE(left) == AOP_CRY){
6512     // c = bit & literal;
6513     if(AOP_TYPE(right) == AOP_LIT){
6514       if(lit & 1) {
6515         if(size && pic16_sameRegs(AOP(result),AOP(left)))
6516           // no change
6517           goto release;
6518         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6519       } else {
6520         // bit(result) = 0;
6521         if(size && (AOP_TYPE(result) == AOP_CRY)){
6522           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6523           goto release;
6524         }
6525         if((AOP_TYPE(result) == AOP_CRY) && ifx){
6526           jumpIfTrue(ifx);
6527           goto release;
6528         }
6529         pic16_emitcode("clr","c");
6530       }
6531     } else {
6532       if (AOP_TYPE(right) == AOP_CRY){
6533         // c = bit & bit;
6534         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6535         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6536       } else {
6537         // c = bit & val;
6538         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6539         // c = lsb
6540         pic16_emitcode("rrc","a");
6541         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6542       }
6543     }
6544     // bit = c
6545     // val = c
6546     if(size)
6547       pic16_outBitC(result);
6548     // if(bit & ...)
6549     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6550       genIfxJump(ifx, "c");           
6551     goto release ;
6552   }
6553
6554   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6555   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6556   if((AOP_TYPE(right) == AOP_LIT) &&
6557      (AOP_TYPE(result) == AOP_CRY) &&
6558      (AOP_TYPE(left) != AOP_CRY)){
6559     int posbit = isLiteralBit(lit);
6560     /* left &  2^n */
6561     if(posbit){
6562       posbit--;
6563       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6564       // bit = left & 2^n
6565       if(size)
6566         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6567       // if(left &  2^n)
6568       else{
6569         if(ifx){
6570 /*
6571           if(IC_TRUE(ifx)) {
6572             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6573             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6574           } else {
6575             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6576             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6577           }
6578 */
6579         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
6580         size = AOP_SIZE(left);
6581
6582         {
6583           int bp = posbit, ofs=0;
6584           
6585             while(bp > 7) {
6586               bp -= 8;
6587               ofs++;
6588             }
6589         
6590           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6591                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
6592
6593         }
6594 /*
6595           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6596                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6597 */
6598           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6599           
6600           ifx->generated = 1;
6601         }
6602         goto release;
6603       }
6604     } else {
6605       symbol *tlbl = newiTempLabel(NULL);
6606       int sizel = AOP_SIZE(left);
6607
6608       if(size)
6609         emitSETC;
6610
6611       while(sizel--) {
6612         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
6613
6614           /* patch provided by Aaron Colwell */
6615           if((posbit = isLiteralBit(bytelit)) != 0) {
6616               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
6617                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
6618                                                 (posbit-1),0, PO_GPR_REGISTER));
6619
6620               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
6621           } else {
6622               if (bytelit == 0xff) {
6623                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
6624                    * a peephole could optimize it out -- VR */
6625                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6626               } else {
6627                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6628                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
6629               }
6630
6631               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
6632                             pic16_popGetLabel(tlbl->key));
6633           }
6634         
6635 #if 0
6636           /* old code, left here for reference -- VR 09/2004 */
6637           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6638           // byte ==  2^n ?
6639           if((posbit = isLiteralBit(bytelit)) != 0)
6640             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6641           else{
6642             if(bytelit != 0x0FFL)
6643               pic16_emitcode("anl","a,%s",
6644                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6645             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6646           }
6647 #endif
6648         }
6649         offset++;
6650       }
6651       // bit = left & literal
6652       if(size) {
6653         emitCLRC;
6654         pic16_emitpLabel(tlbl->key);
6655       }
6656       // if(left & literal)
6657       else {
6658         if(ifx) {
6659           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
6660           pic16_emitpLabel(tlbl->key);
6661           ifx->generated = 1;
6662         }
6663         goto release;
6664       }
6665     }
6666
6667     pic16_outBitC(result);
6668     goto release ;
6669   }
6670
6671   /* if left is same as result */
6672   if(pic16_sameRegs(AOP(result),AOP(left))){
6673     int know_W = -1;
6674     for(;size--; offset++,lit>>=8) {
6675       if(AOP_TYPE(right) == AOP_LIT){
6676         switch(lit & 0xff) {
6677         case 0x00:
6678           /*  and'ing with 0 has clears the result */
6679 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6680           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6681           break;
6682         case 0xff:
6683           /* and'ing with 0xff is a nop when the result and left are the same */
6684           break;
6685
6686         default:
6687           {
6688             int p = my_powof2( (~lit) & 0xff );
6689             if(p>=0) {
6690               /* only one bit is set in the literal, so use a bcf instruction */
6691 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6692               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6693
6694             } else {
6695               pic16_emitcode("movlw","0x%x", (lit & 0xff));
6696               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6697               if(know_W != (lit&0xff))
6698                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6699               know_W = lit &0xff;
6700               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6701             }
6702           }    
6703         }
6704       } else {
6705         if (AOP_TYPE(left) == AOP_ACC) {
6706           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6707         } else {                    
6708           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6709           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6710
6711         }
6712       }
6713     }
6714
6715   } else {
6716     // left & result in different registers
6717     if(AOP_TYPE(result) == AOP_CRY){
6718       // result = bit
6719       // if(size), result in bit
6720       // if(!size && ifx), conditional oper: if(left & right)
6721       symbol *tlbl = newiTempLabel(NULL);
6722       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6723       if(size)
6724         pic16_emitcode("setb","c");
6725       while(sizer--){
6726         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6727         pic16_emitcode("anl","a,%s",
6728                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6729         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6730         offset++;
6731       }
6732       if(size){
6733         CLRC;
6734         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6735         pic16_outBitC(result);
6736       } else if(ifx)
6737         jmpTrueOrFalse(ifx, tlbl);
6738     } else {
6739       for(;(size--);offset++) {
6740         // normal case
6741         // result = left & right
6742         if(AOP_TYPE(right) == AOP_LIT){
6743           int t = (lit >> (offset*8)) & 0x0FFL;
6744           switch(t) { 
6745           case 0x00:
6746             pic16_emitcode("clrf","%s",
6747                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6748             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6749             break;
6750           case 0xff:
6751             pic16_emitcode("movf","%s,w",
6752                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6753             pic16_emitcode("movwf","%s",
6754                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6755             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6756             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6757             break;
6758           default:
6759             pic16_emitcode("movlw","0x%x",t);
6760             pic16_emitcode("andwf","%s,w",
6761                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6762             pic16_emitcode("movwf","%s",
6763                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6764               
6765             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6766             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6767             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6768           }
6769           continue;
6770         }
6771
6772         if (AOP_TYPE(left) == AOP_ACC) {
6773           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6774           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6775         } else {
6776           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6777           pic16_emitcode("andwf","%s,w",
6778                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6779           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6780           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6781         }
6782         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6783         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6784       }
6785     }
6786   }
6787
6788   release :
6789     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6790   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6791   pic16_freeAsmop(result,NULL,ic,TRUE);     
6792 }
6793
6794 /*-----------------------------------------------------------------*/
6795 /* genOr  - code for or                                            */
6796 /*-----------------------------------------------------------------*/
6797 static void genOr (iCode *ic, iCode *ifx)
6798 {
6799     operand *left, *right, *result;
6800     int size, offset=0;
6801     unsigned long lit = 0L;
6802
6803     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6804
6805     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6806     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6807     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6808
6809     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6810
6811     /* if left is a literal & right is not then exchange them */
6812     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6813         AOP_NEEDSACC(left)) {
6814         operand *tmp = right ;
6815         right = left;
6816         left = tmp;
6817     }
6818
6819     /* if result = right then exchange them */
6820     if(pic16_sameRegs(AOP(result),AOP(right))){
6821         operand *tmp = right ;
6822         right = left;
6823         left = tmp;
6824     }
6825
6826     /* if right is bit then exchange them */
6827     if (AOP_TYPE(right) == AOP_CRY &&
6828         AOP_TYPE(left) != AOP_CRY){
6829         operand *tmp = right ;
6830         right = left;
6831         left = tmp;
6832     }
6833
6834     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6835
6836     if(AOP_TYPE(right) == AOP_LIT)
6837         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6838
6839     size = AOP_SIZE(result);
6840
6841     // if(bit | yy)
6842     // xx = bit | yy;
6843     if (AOP_TYPE(left) == AOP_CRY){
6844         if(AOP_TYPE(right) == AOP_LIT){
6845             // c = bit & literal;
6846             if(lit){
6847                 // lit != 0 => result = 1
6848                 if(AOP_TYPE(result) == AOP_CRY){
6849                   if(size)
6850                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6851                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6852                   //     AOP(result)->aopu.aop_dir,
6853                   //     AOP(result)->aopu.aop_dir);
6854                     else if(ifx)
6855                         continueIfTrue(ifx);
6856                     goto release;
6857                 }
6858             } else {
6859                 // lit == 0 => result = left
6860                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6861                     goto release;
6862                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6863             }
6864         } else {
6865             if (AOP_TYPE(right) == AOP_CRY){
6866               if(pic16_sameRegs(AOP(result),AOP(left))){
6867                 // c = bit | bit;
6868                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6869                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6870                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6871
6872                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6873                          AOP(result)->aopu.aop_dir,
6874                          AOP(result)->aopu.aop_dir);
6875                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6876                          AOP(right)->aopu.aop_dir,
6877                          AOP(right)->aopu.aop_dir);
6878                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6879                          AOP(result)->aopu.aop_dir,
6880                          AOP(result)->aopu.aop_dir);
6881               } else {
6882                 if( AOP_TYPE(result) == AOP_ACC) {
6883                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6884                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6885                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6886                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6887
6888                 } else {
6889
6890                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6891                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6892                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6893                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6894
6895                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6896                                  AOP(result)->aopu.aop_dir,
6897                                  AOP(result)->aopu.aop_dir);
6898                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6899                                  AOP(right)->aopu.aop_dir,
6900                                  AOP(right)->aopu.aop_dir);
6901                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6902                                  AOP(left)->aopu.aop_dir,
6903                                  AOP(left)->aopu.aop_dir);
6904                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6905                                  AOP(result)->aopu.aop_dir,
6906                                  AOP(result)->aopu.aop_dir);
6907                 }
6908               }
6909             } else {
6910                 // c = bit | val;
6911                 symbol *tlbl = newiTempLabel(NULL);
6912                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6913
6914
6915                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6916                 if( AOP_TYPE(right) == AOP_ACC) {
6917                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6918                   emitSKPNZ;
6919                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6920                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6921                 }
6922
6923
6924
6925                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6926                     pic16_emitcode(";XXX setb","c");
6927                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6928                          AOP(left)->aopu.aop_dir,tlbl->key+100);
6929                 pic16_toBoolean(right);
6930                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6931                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6932                     jmpTrueOrFalse(ifx, tlbl);
6933                     goto release;
6934                 } else {
6935                     CLRC;
6936                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6937                 }
6938             }
6939         }
6940         // bit = c
6941         // val = c
6942         if(size)
6943             pic16_outBitC(result);
6944         // if(bit | ...)
6945         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6946             genIfxJump(ifx, "c");           
6947         goto release ;
6948     }
6949
6950     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6951     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6952     if((AOP_TYPE(right) == AOP_LIT) &&
6953        (AOP_TYPE(result) == AOP_CRY) &&
6954        (AOP_TYPE(left) != AOP_CRY)){
6955         if(lit){
6956           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6957             // result = 1
6958             if(size)
6959                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6960             else 
6961                 continueIfTrue(ifx);
6962             goto release;
6963         } else {
6964           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6965             // lit = 0, result = boolean(left)
6966             if(size)
6967                 pic16_emitcode(";XXX setb","c");
6968             pic16_toBoolean(right);
6969             if(size){
6970                 symbol *tlbl = newiTempLabel(NULL);
6971                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6972                 CLRC;
6973                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6974             } else {
6975                 genIfxJump (ifx,"a");
6976                 goto release;
6977             }
6978         }
6979         pic16_outBitC(result);
6980         goto release ;
6981     }
6982
6983     /* if left is same as result */
6984     if(pic16_sameRegs(AOP(result),AOP(left))){
6985       int know_W = -1;
6986       for(;size--; offset++,lit>>=8) {
6987         if(AOP_TYPE(right) == AOP_LIT){
6988           if((lit & 0xff) == 0)
6989             /*  or'ing with 0 has no effect */
6990             continue;
6991           else {
6992             int p = my_powof2(lit & 0xff);
6993             if(p>=0) {
6994               /* only one bit is set in the literal, so use a bsf instruction */
6995               pic16_emitpcode(POC_BSF,
6996                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6997             } else {
6998               if(know_W != (lit & 0xff))
6999                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7000               know_W = lit & 0xff;
7001               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7002             }
7003                     
7004           }
7005         } else {
7006           if (AOP_TYPE(left) == AOP_ACC) {
7007             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7008             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7009           } else {                  
7010             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7011             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7012
7013             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7014             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7015
7016           }
7017         }
7018       }
7019     } else {
7020         // left & result in different registers
7021         if(AOP_TYPE(result) == AOP_CRY){
7022             // result = bit
7023             // if(size), result in bit
7024             // if(!size && ifx), conditional oper: if(left | right)
7025             symbol *tlbl = newiTempLabel(NULL);
7026             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7027             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7028
7029
7030             if(size)
7031                 pic16_emitcode(";XXX setb","c");
7032             while(sizer--){
7033                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7034                 pic16_emitcode(";XXX orl","a,%s",
7035                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7036                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7037                 offset++;
7038             }
7039             if(size){
7040                 CLRC;
7041                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7042                 pic16_outBitC(result);
7043             } else if(ifx)
7044                 jmpTrueOrFalse(ifx, tlbl);
7045         } else for(;(size--);offset++){
7046           // normal case
7047           // result = left & right
7048           if(AOP_TYPE(right) == AOP_LIT){
7049             int t = (lit >> (offset*8)) & 0x0FFL;
7050             switch(t) { 
7051             case 0x00:
7052               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7053               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7054
7055               pic16_emitcode("movf","%s,w",
7056                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7057               pic16_emitcode("movwf","%s",
7058                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7059               break;
7060             default:
7061               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7062               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7063               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7064
7065               pic16_emitcode("movlw","0x%x",t);
7066               pic16_emitcode("iorwf","%s,w",
7067                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7068               pic16_emitcode("movwf","%s",
7069                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7070               
7071             }
7072             continue;
7073           }
7074
7075           // faster than result <- left, anl result,right
7076           // and better if result is SFR
7077           if (AOP_TYPE(left) == AOP_ACC) {
7078             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7079             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7080           } else {
7081             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7082             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7083
7084             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7085             pic16_emitcode("iorwf","%s,w",
7086                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7087           }
7088           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7089           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7090         }
7091     }
7092
7093 release :
7094     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7095     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7096     pic16_freeAsmop(result,NULL,ic,TRUE);     
7097 }
7098
7099 /*-----------------------------------------------------------------*/
7100 /* genXor - code for xclusive or                                   */
7101 /*-----------------------------------------------------------------*/
7102 static void genXor (iCode *ic, iCode *ifx)
7103 {
7104   operand *left, *right, *result;
7105   int size, offset=0;
7106   unsigned long lit = 0L;
7107
7108   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7109
7110   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7111   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7112   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7113
7114   /* if left is a literal & right is not ||
7115      if left needs acc & right does not */
7116   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7117       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7118     operand *tmp = right ;
7119     right = left;
7120     left = tmp;
7121   }
7122
7123   /* if result = right then exchange them */
7124   if(pic16_sameRegs(AOP(result),AOP(right))){
7125     operand *tmp = right ;
7126     right = left;
7127     left = tmp;
7128   }
7129
7130   /* if right is bit then exchange them */
7131   if (AOP_TYPE(right) == AOP_CRY &&
7132       AOP_TYPE(left) != AOP_CRY){
7133     operand *tmp = right ;
7134     right = left;
7135     left = tmp;
7136   }
7137   if(AOP_TYPE(right) == AOP_LIT)
7138     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7139
7140   size = AOP_SIZE(result);
7141
7142   // if(bit ^ yy)
7143   // xx = bit ^ yy;
7144   if (AOP_TYPE(left) == AOP_CRY){
7145     if(AOP_TYPE(right) == AOP_LIT){
7146       // c = bit & literal;
7147       if(lit>>1){
7148         // lit>>1  != 0 => result = 1
7149         if(AOP_TYPE(result) == AOP_CRY){
7150           if(size)
7151             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
7152             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7153           else if(ifx)
7154             continueIfTrue(ifx);
7155           goto release;
7156         }
7157         pic16_emitcode("setb","c");
7158       } else{
7159         // lit == (0 or 1)
7160         if(lit == 0){
7161           // lit == 0, result = left
7162           if(size && pic16_sameRegs(AOP(result),AOP(left)))
7163             goto release;
7164           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7165         } else{
7166           // lit == 1, result = not(left)
7167           if(size && pic16_sameRegs(AOP(result),AOP(left))){
7168             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
7169             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
7170             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7171             goto release;
7172           } else {
7173             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7174             pic16_emitcode("cpl","c");
7175           }
7176         }
7177       }
7178
7179     } else {
7180       // right != literal
7181       symbol *tlbl = newiTempLabel(NULL);
7182       if (AOP_TYPE(right) == AOP_CRY){
7183         // c = bit ^ bit;
7184         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7185       }
7186       else{
7187         int sizer = AOP_SIZE(right);
7188         // c = bit ^ val
7189         // if val>>1 != 0, result = 1
7190         pic16_emitcode("setb","c");
7191         while(sizer){
7192           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
7193           if(sizer == 1)
7194             // test the msb of the lsb
7195             pic16_emitcode("anl","a,#0xfe");
7196           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7197           sizer--;
7198         }
7199         // val = (0,1)
7200         pic16_emitcode("rrc","a");
7201       }
7202       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
7203       pic16_emitcode("cpl","c");
7204       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
7205     }
7206     // bit = c
7207     // val = c
7208     if(size)
7209       pic16_outBitC(result);
7210     // if(bit | ...)
7211     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7212       genIfxJump(ifx, "c");           
7213     goto release ;
7214   }
7215
7216   if(pic16_sameRegs(AOP(result),AOP(left))){
7217     /* if left is same as result */
7218     for(;size--; offset++) {
7219       if(AOP_TYPE(right) == AOP_LIT){
7220         int t  = (lit >> (offset*8)) & 0x0FFL;
7221         if(t == 0x00L)
7222           continue;
7223         else
7224           if (IS_AOP_PREG(left)) {
7225             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7226             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7227             pic16_aopPut(AOP(result),"a",offset);
7228           } else {
7229             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7230             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7231             pic16_emitcode("xrl","%s,%s",
7232                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7233                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7234           }
7235       } else {
7236         if (AOP_TYPE(left) == AOP_ACC)
7237           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7238         else {
7239           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7240           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7241 /*
7242           if (IS_AOP_PREG(left)) {
7243             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7244             pic16_aopPut(AOP(result),"a",offset);
7245           } else
7246             pic16_emitcode("xrl","%s,a",
7247                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7248 */
7249         }
7250       }
7251     }
7252   } else {
7253     // left & result in different registers
7254     if(AOP_TYPE(result) == AOP_CRY){
7255       // result = bit
7256       // if(size), result in bit
7257       // if(!size && ifx), conditional oper: if(left ^ right)
7258       symbol *tlbl = newiTempLabel(NULL);
7259       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7260       if(size)
7261         pic16_emitcode("setb","c");
7262       while(sizer--){
7263         if((AOP_TYPE(right) == AOP_LIT) &&
7264            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7265           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7266         } else {
7267           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7268           pic16_emitcode("xrl","a,%s",
7269                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7270         }
7271         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7272         offset++;
7273       }
7274       if(size){
7275         CLRC;
7276         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7277         pic16_outBitC(result);
7278       } else if(ifx)
7279         jmpTrueOrFalse(ifx, tlbl);
7280     } else for(;(size--);offset++){
7281       // normal case
7282       // result = left & right
7283       if(AOP_TYPE(right) == AOP_LIT){
7284         int t = (lit >> (offset*8)) & 0x0FFL;
7285         switch(t) { 
7286         case 0x00:
7287           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7288           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7289           pic16_emitcode("movf","%s,w",
7290                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7291           pic16_emitcode("movwf","%s",
7292                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7293           break;
7294         case 0xff:
7295           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7296           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7297           pic16_emitcode("comf","%s,w",
7298                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7299           pic16_emitcode("movwf","%s",
7300                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7301           break;
7302         default:
7303           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7304           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7305           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7306           pic16_emitcode("movlw","0x%x",t);
7307           pic16_emitcode("xorwf","%s,w",
7308                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7309           pic16_emitcode("movwf","%s",
7310                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7311
7312         }
7313         continue;
7314       }
7315
7316       // faster than result <- left, anl result,right
7317       // and better if result is SFR
7318       if (AOP_TYPE(left) == AOP_ACC) {
7319         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7320         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7321       } else {
7322         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7323         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7324         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7325         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7326       }
7327       if ( AOP_TYPE(result) != AOP_ACC){
7328         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7329         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7330       }
7331     }
7332   }
7333
7334   release :
7335     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7336   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7337   pic16_freeAsmop(result,NULL,ic,TRUE);     
7338 }
7339
7340 /*-----------------------------------------------------------------*/
7341 /* genInline - write the inline code out                           */
7342 /*-----------------------------------------------------------------*/
7343 static void genInline (iCode *ic)
7344 {
7345   char *buffer, *bp, *bp1;
7346     
7347         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7348
7349         _G.inLine += (!options.asmpeep);
7350
7351         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7352         strcpy(buffer,IC_INLINE(ic));
7353
7354 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7355
7356         /* emit each line as a code */
7357         while (*bp) {
7358                 if (*bp == '\n') {
7359                         *bp++ = '\0';
7360
7361                         if(*bp1)
7362                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7363                         bp1 = bp;
7364                 } else {
7365                         if (*bp == ':') {
7366                                 bp++;
7367                                 *bp = '\0';
7368                                 bp++;
7369
7370                                 /* print label, use this special format with NULL directive
7371                                  * to denote that the argument should not be indented with tab */
7372                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7373                                 bp1 = bp;
7374                         } else
7375                                 bp++;
7376                 }
7377         }
7378
7379         if ((bp1 != bp) && *bp1)
7380                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7381
7382
7383     Safe_free(buffer);
7384
7385     _G.inLine -= (!options.asmpeep);
7386 }
7387
7388 /*-----------------------------------------------------------------*/
7389 /* genRRC - rotate right with carry                                */
7390 /*-----------------------------------------------------------------*/
7391 static void genRRC (iCode *ic)
7392 {
7393   operand *left , *result ;
7394   int size, offset = 0, same;
7395
7396   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7397
7398   /* rotate right with carry */
7399   left = IC_LEFT(ic);
7400   result=IC_RESULT(ic);
7401   pic16_aopOp (left,ic,FALSE);
7402   pic16_aopOp (result,ic,FALSE);
7403
7404   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7405
7406   same = pic16_sameRegs(AOP(result),AOP(left));
7407
7408   size = AOP_SIZE(result);    
7409
7410   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7411
7412   /* get the lsb and put it into the carry */
7413   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7414
7415   offset = 0 ;
7416
7417   while(size--) {
7418
7419     if(same) {
7420       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7421     } else {
7422       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7423       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7424     }
7425
7426     offset++;
7427   }
7428
7429   pic16_freeAsmop(left,NULL,ic,TRUE);
7430   pic16_freeAsmop(result,NULL,ic,TRUE);
7431 }
7432
7433 /*-----------------------------------------------------------------*/
7434 /* genRLC - generate code for rotate left with carry               */
7435 /*-----------------------------------------------------------------*/
7436 static void genRLC (iCode *ic)
7437 {    
7438   operand *left , *result ;
7439   int size, offset = 0;
7440   int same;
7441
7442   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7443   /* rotate right with carry */
7444   left = IC_LEFT(ic);
7445   result=IC_RESULT(ic);
7446   pic16_aopOp (left,ic,FALSE);
7447   pic16_aopOp (result,ic,FALSE);
7448
7449   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7450
7451   same = pic16_sameRegs(AOP(result),AOP(left));
7452
7453   /* move it to the result */
7454   size = AOP_SIZE(result);    
7455
7456   /* get the msb and put it into the carry */
7457   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7458
7459   offset = 0 ;
7460
7461   while(size--) {
7462
7463     if(same) {
7464       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7465     } else {
7466       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7467       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7468     }
7469
7470     offset++;
7471   }
7472
7473
7474   pic16_freeAsmop(left,NULL,ic,TRUE);
7475   pic16_freeAsmop(result,NULL,ic,TRUE);
7476 }
7477
7478
7479 /* gpasm can get the highest order bit with HIGH/UPPER
7480  * so the following probably is not needed -- VR */
7481  
7482 /*-----------------------------------------------------------------*/
7483 /* genGetHbit - generates code get highest order bit               */
7484 /*-----------------------------------------------------------------*/
7485 static void genGetHbit (iCode *ic)
7486 {
7487     operand *left, *result;
7488     left = IC_LEFT(ic);
7489     result=IC_RESULT(ic);
7490     pic16_aopOp (left,ic,FALSE);
7491     pic16_aopOp (result,ic,FALSE);
7492
7493     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7494     /* get the highest order byte into a */
7495     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7496     if(AOP_TYPE(result) == AOP_CRY){
7497         pic16_emitcode("rlc","a");
7498         pic16_outBitC(result);
7499     }
7500     else{
7501         pic16_emitcode("rl","a");
7502         pic16_emitcode("anl","a,#0x01");
7503         pic16_outAcc(result);
7504     }
7505
7506
7507     pic16_freeAsmop(left,NULL,ic,TRUE);
7508     pic16_freeAsmop(result,NULL,ic,TRUE);
7509 }
7510
7511 #if 0
7512 /*-----------------------------------------------------------------*/
7513 /* AccRol - rotate left accumulator by known count                 */
7514 /*-----------------------------------------------------------------*/
7515 static void AccRol (int shCount)
7516 {
7517     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7518     shCount &= 0x0007;              // shCount : 0..7
7519     switch(shCount){
7520         case 0 :
7521             break;
7522         case 1 :
7523             pic16_emitcode("rl","a");
7524             break;
7525         case 2 :
7526             pic16_emitcode("rl","a");
7527             pic16_emitcode("rl","a");
7528             break;
7529         case 3 :
7530             pic16_emitcode("swap","a");
7531             pic16_emitcode("rr","a");
7532             break;
7533         case 4 :
7534             pic16_emitcode("swap","a");
7535             break;
7536         case 5 :
7537             pic16_emitcode("swap","a");
7538             pic16_emitcode("rl","a");
7539             break;
7540         case 6 :
7541             pic16_emitcode("rr","a");
7542             pic16_emitcode("rr","a");
7543             break;
7544         case 7 :
7545             pic16_emitcode("rr","a");
7546             break;
7547     }
7548 }
7549 #endif
7550
7551 /*-----------------------------------------------------------------*/
7552 /* AccLsh - left shift accumulator by known count                  */
7553 /*-----------------------------------------------------------------*/
7554 static void AccLsh (int shCount)
7555 {
7556         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7557         switch(shCount){
7558                 case 0 :
7559                         return;
7560                         break;
7561                 case 1 :
7562                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7563                         break;
7564                 case 2 :
7565                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7566                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7567                         break;
7568                 case 3 :
7569                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7570                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7571                         break;
7572                 case 4 :
7573                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7574                         break;
7575                 case 5 :
7576                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7577                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7578                         break;
7579                 case 6 :
7580                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7581                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7582                         break;
7583                 case 7 :
7584                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7585                         break;
7586         }
7587
7588         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7589 }
7590
7591 /*-----------------------------------------------------------------*/
7592 /* AccRsh - right shift accumulator by known count                 */
7593 /*-----------------------------------------------------------------*/
7594 static void AccRsh (int shCount, int andmask)
7595 {
7596         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7597         switch(shCount){
7598                 case 0 :
7599                         return; break;
7600                 case 1 :
7601                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7602 //                      andmask = 0;    /* no need */
7603                         break;
7604                 case 2 :
7605                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7606                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7607 //                      andmask = 0;    /* no need */
7608                         break;
7609                 case 3 :
7610                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7611                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7612                         break;
7613                 case 4 :
7614                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7615                         break;
7616                 case 5 :
7617                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7618                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7619                         break;
7620                 case 6 :
7621                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7622                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7623                         break;
7624                 case 7 :
7625                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7626                         break;
7627         }
7628         
7629         if(andmask)
7630                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7631         else
7632                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7633 }
7634
7635 #if 0
7636 /*-----------------------------------------------------------------*/
7637 /* AccSRsh - signed right shift accumulator by known count                 */
7638 /*-----------------------------------------------------------------*/
7639 static void AccSRsh (int shCount)
7640 {
7641     symbol *tlbl ;
7642     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7643     if(shCount != 0){
7644         if(shCount == 1){
7645             pic16_emitcode("mov","c,acc.7");
7646             pic16_emitcode("rrc","a");
7647         } else if(shCount == 2){
7648             pic16_emitcode("mov","c,acc.7");
7649             pic16_emitcode("rrc","a");
7650             pic16_emitcode("mov","c,acc.7");
7651             pic16_emitcode("rrc","a");
7652         } else {
7653             tlbl = newiTempLabel(NULL);
7654             /* rotate right accumulator */
7655             AccRol(8 - shCount);
7656             /* and kill the higher order bits */
7657             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7658             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7659             pic16_emitcode("orl","a,#0x%02x",
7660                      (unsigned char)~SRMask[shCount]);
7661             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7662         }
7663     }
7664 }
7665 #endif
7666 /*-----------------------------------------------------------------*/
7667 /* shiftR1Left2Result - shift right one byte from left to result   */
7668 /*-----------------------------------------------------------------*/
7669 static void shiftR1Left2ResultSigned (operand *left, int offl,
7670                                 operand *result, int offr,
7671                                 int shCount)
7672 {
7673   int same;
7674
7675   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7676
7677   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7678
7679   switch(shCount) {
7680   case 1:
7681     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7682     if(same) 
7683       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7684     else {
7685       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7686       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7687     }
7688
7689     break;
7690   case 2:
7691
7692     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7693     if(same) 
7694       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7695     else {
7696       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7697       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7698     }
7699     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7700     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7701
7702     break;
7703
7704   case 3:
7705     if(same)
7706       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7707     else {
7708       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7709       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7710     }
7711
7712     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7713     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7714     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7715
7716     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7717     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7718
7719     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7720     break;
7721
7722   case 4:
7723     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7724     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
7725     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7726     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
7727     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7728     break;
7729   case 5:
7730     if(same) {
7731       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
7732     } else {
7733       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
7734       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7735     }
7736     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
7737     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
7738     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7739     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
7740     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7741     break;
7742
7743   case 6:
7744     if(same) {
7745       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7746       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7747       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7748       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7749       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7750       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7751     } else {
7752       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7753       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7754       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7755       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7756       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7757     }
7758     break;
7759
7760   case 7:
7761     if(same) {
7762       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7763       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7764       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7765       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7766     } else {
7767       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7768       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7769       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7770     }
7771
7772   default:
7773     break;
7774   }
7775 }
7776
7777 /*-----------------------------------------------------------------*/
7778 /* shiftR1Left2Result - shift right one byte from left to result   */
7779 /*-----------------------------------------------------------------*/
7780 static void shiftR1Left2Result (operand *left, int offl,
7781                                 operand *result, int offr,
7782                                 int shCount, int sign)
7783 {
7784   int same;
7785
7786   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7787
7788   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7789
7790   /* Copy the msb into the carry if signed. */
7791   if(sign) {
7792     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7793     return;
7794   }
7795
7796
7797
7798   switch(shCount) {
7799   case 1:
7800     emitCLRC;
7801     if(same) 
7802       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7803     else {
7804       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7805       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7806     }
7807     break;
7808   case 2:
7809     emitCLRC;
7810     if(same) {
7811       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7812     } else {
7813       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7814       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7815     }
7816     emitCLRC;
7817     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7818
7819     break;
7820   case 3:
7821     if(same)
7822       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7823     else {
7824       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7825       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7826     }
7827
7828     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7829     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7830     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7831     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7832     break;
7833       
7834   case 4:
7835     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7836     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7837     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7838     break;
7839
7840   case 5:
7841     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7842     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7843     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7844     emitCLRC;
7845     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7846
7847     break;
7848   case 6:
7849
7850     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
7851     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7852     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7853     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7854     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7855     break;
7856
7857   case 7:
7858
7859     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7860     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7861     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7862
7863     break;
7864
7865   default:
7866     break;
7867   }
7868 }
7869
7870 /*-----------------------------------------------------------------*/
7871 /* shiftL1Left2Result - shift left one byte from left to result    */
7872 /*-----------------------------------------------------------------*/
7873 static void shiftL1Left2Result (operand *left, int offl,
7874                                 operand *result, int offr, int shCount)
7875 {
7876   int same;
7877
7878   //    char *l;
7879   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7880
7881   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7882   DEBUGpic16_emitcode ("; ***","same =  %d",same);
7883     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7884     //    MOVA(l);
7885     /* shift left accumulator */
7886     //AccLsh(shCount); // don't comment out just yet...
7887   //    pic16_aopPut(AOP(result),"a",offr);
7888
7889   switch(shCount) {
7890   case 1:
7891     /* Shift left 1 bit position */
7892     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7893     if(same) {
7894       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7895     } else {
7896       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7897       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7898     }
7899     break;
7900   case 2:
7901     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7902     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7903     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7904     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7905     break;
7906   case 3:
7907     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7908     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7909     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7910     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7911     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7912     break;
7913   case 4:
7914     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7915     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7916     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7917     break;
7918   case 5:
7919     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7920     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7921     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7922     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7923     break;
7924   case 6:
7925     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7926     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7927     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7928     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7929     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7930     break;
7931   case 7:
7932     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7933     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7934     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7935     break;
7936
7937   default:
7938     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7939   }
7940
7941 }
7942
7943 /*-----------------------------------------------------------------*/
7944 /* movLeft2Result - move byte from left to result                  */
7945 /*-----------------------------------------------------------------*/
7946 static void movLeft2Result (operand *left, int offl,
7947                             operand *result, int offr)
7948 {
7949   char *l;
7950   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7951   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7952     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7953
7954     if (*l == '@' && (IS_AOP_PREG(result))) {
7955       pic16_emitcode("mov","a,%s",l);
7956       pic16_aopPut(AOP(result),"a",offr);
7957     } else {
7958       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7959       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7960     }
7961   }
7962 }
7963
7964 /*-----------------------------------------------------------------*/
7965 /* shiftL2Left2Result - shift left two bytes from left to result   */
7966 /*-----------------------------------------------------------------*/
7967 static void shiftL2Left2Result (operand *left, int offl,
7968                                 operand *result, int offr, int shCount)
7969 {
7970   int same = pic16_sameRegs(AOP(result), AOP(left));
7971   int i;
7972
7973   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7974
7975   if (same && (offl != offr)) { // shift bytes
7976     if (offr > offl) {
7977        for(i=1;i>-1;i--) {
7978          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7979          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7980        }
7981     } else { // just treat as different later on
7982                 same = 0;
7983     }
7984   }
7985
7986   if(same) {
7987     switch(shCount) {
7988     case 0:
7989       break;
7990     case 1:
7991     case 2:
7992     case 3:
7993
7994       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7995       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7996       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7997
7998       while(--shCount) {
7999                 emitCLRC;
8000                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8001                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8002       }
8003
8004       break;
8005     case 4:
8006     case 5:
8007       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8008       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8009       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8010       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8011       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8012       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8013       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8014       if(shCount >=5) {
8015                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8016                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8017       }
8018       break;
8019     case 6:
8020       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8021       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8022       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8023       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8024       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8025       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8026       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8027       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8028       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8029       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8030       break;
8031     case 7:
8032       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8033       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8034       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8035       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8036       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8037     }
8038
8039   } else {
8040     switch(shCount) {
8041     case 0:
8042       break;
8043     case 1:
8044     case 2:
8045     case 3:
8046       /* note, use a mov/add for the shift since the mov has a
8047          chance of getting optimized out */
8048       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8049       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8050       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8051       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8052       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8053
8054       while(--shCount) {
8055                 emitCLRC;
8056                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8057                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8058       }
8059       break;
8060
8061     case 4:
8062     case 5:
8063       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8064       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8065       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8066       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8067       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8068       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8069       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8070       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8071
8072
8073       if(shCount == 5) {
8074                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8075                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8076       }
8077       break;
8078     case 6:
8079       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8080       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8081       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8082       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8083
8084       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8085       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8086       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8087       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8088       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8089       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8090       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8091       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8092       break;
8093     case 7:
8094       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8095       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8096       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8097       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8098       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8099     }
8100   }
8101
8102 }
8103 /*-----------------------------------------------------------------*/
8104 /* shiftR2Left2Result - shift right two bytes from left to result  */
8105 /*-----------------------------------------------------------------*/
8106 static void shiftR2Left2Result (operand *left, int offl,
8107                                 operand *result, int offr,
8108                                 int shCount, int sign)
8109 {
8110   int same = pic16_sameRegs(AOP(result), AOP(left));
8111   int i;
8112   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8113
8114   if (same && (offl != offr)) { // shift right bytes
8115     if (offr < offl) {
8116        for(i=0;i<2;i++) {
8117          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8118          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8119        }
8120     } else { // just treat as different later on
8121                 same = 0;
8122     }
8123   }
8124
8125   switch(shCount) {
8126   case 0:
8127     break;
8128   case 1:
8129   case 2:
8130   case 3:
8131     if(sign)
8132       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8133     else
8134       emitCLRC;
8135
8136     if(same) {
8137       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8138       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8139     } else {
8140       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8141       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8142       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8143       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8144     }
8145
8146     while(--shCount) {
8147       if(sign)
8148                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8149       else
8150                 emitCLRC;
8151       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8152       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8153     }
8154     break;
8155   case 4:
8156   case 5:
8157     if(same) {
8158
8159       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
8160       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
8161       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8162
8163       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8164       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
8165       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8166       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8167     } else {
8168       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8169       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8170       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8171
8172       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8173       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8174       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8175       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8176       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8177     }
8178
8179     if(shCount >=5) {
8180       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8181       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8182     }
8183
8184     if(sign) {
8185       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
8186       pic16_emitpcode(POC_BTFSC, 
8187                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
8188       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8189     }
8190
8191     break;
8192
8193   case 6:
8194     if(same) {
8195
8196       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8197       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8198
8199       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8200       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8201       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8202       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8203       if(sign) {
8204         pic16_emitpcode(POC_BTFSC, 
8205                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8206         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8207       }
8208       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8209       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
8210       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8211       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8212     } else {
8213       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8214       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8215       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8216       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8217       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8218       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8219       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8220       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8221       if(sign) {
8222         pic16_emitpcode(POC_BTFSC, 
8223                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8224         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8225       }
8226       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8227       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8228
8229         
8230     }
8231
8232     break;
8233   case 7:
8234     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8235     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8236     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8237     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8238     if(sign) {
8239       emitSKPNC;
8240       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8241     } else 
8242       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8243   }
8244 }
8245
8246
8247 /*-----------------------------------------------------------------*/
8248 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8249 /*-----------------------------------------------------------------*/
8250 static void shiftLLeftOrResult (operand *left, int offl,
8251                                 operand *result, int offr, int shCount)
8252 {
8253     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8254
8255     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8256     /* shift left accumulator */
8257     AccLsh(shCount);
8258     /* or with result */
8259     /* back to result */
8260     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8261 }
8262
8263 /*-----------------------------------------------------------------*/
8264 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8265 /*-----------------------------------------------------------------*/
8266 static void shiftRLeftOrResult (operand *left, int offl,
8267                                 operand *result, int offr, int shCount)
8268 {
8269     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8270     
8271     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8272     /* shift right accumulator */
8273     AccRsh(shCount, 1);
8274     /* or with result */
8275     /* back to result */
8276     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8277 }
8278
8279 /*-----------------------------------------------------------------*/
8280 /* genlshOne - left shift a one byte quantity by known count       */
8281 /*-----------------------------------------------------------------*/
8282 static void genlshOne (operand *result, operand *left, int shCount)
8283 {       
8284     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8285     shiftL1Left2Result(left, LSB, result, LSB, shCount);
8286 }
8287
8288 /*-----------------------------------------------------------------*/
8289 /* genlshTwo - left shift two bytes by known amount != 0           */
8290 /*-----------------------------------------------------------------*/
8291 static void genlshTwo (operand *result,operand *left, int shCount)
8292 {
8293     int size;
8294     
8295     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8296     size = pic16_getDataSize(result);
8297
8298     /* if shCount >= 8 */
8299     if (shCount >= 8) {
8300         shCount -= 8 ;
8301
8302         if (size > 1){
8303             if (shCount)
8304                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8305             else 
8306                 movLeft2Result(left, LSB, result, MSB16);
8307         }
8308         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8309     }
8310
8311     /*  1 <= shCount <= 7 */
8312     else {  
8313         if(size == 1)
8314             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
8315         else 
8316             shiftL2Left2Result(left, LSB, result, LSB, shCount);
8317     }
8318 }
8319
8320 /*-----------------------------------------------------------------*/
8321 /* shiftLLong - shift left one long from left to result            */
8322 /* offr = LSB or MSB16                                             */
8323 /*-----------------------------------------------------------------*/
8324 static void shiftLLong (operand *left, operand *result, int offr )
8325 {
8326     int size = AOP_SIZE(result);
8327     int same = pic16_sameRegs(AOP(left),AOP(result));
8328         int i;
8329
8330     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8331
8332         if (same && (offr == MSB16)) { //shift one byte
8333                 for(i=size-1;i>=MSB16;i--) {
8334                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8335                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8336                 }
8337         } else {
8338                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8339         }
8340         
8341     if (size >= LSB+offr ){
8342                 if (same) {
8343                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8344                 } else {
8345                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8346                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8347                 }
8348          }
8349
8350     if(size >= MSB16+offr){
8351                 if (same) {
8352                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8353                 } else {
8354                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8355                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8356                 }
8357     }
8358
8359     if(size >= MSB24+offr){
8360                 if (same) {
8361                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8362                 } else {
8363                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8364                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8365                 }
8366     }
8367
8368     if(size > MSB32+offr){
8369                 if (same) {
8370                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8371                 } else {
8372                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8373                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8374                 }
8375     }
8376     if(offr != LSB)
8377                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8378
8379 }
8380
8381 /*-----------------------------------------------------------------*/
8382 /* genlshFour - shift four byte by a known amount != 0             */
8383 /*-----------------------------------------------------------------*/
8384 static void genlshFour (operand *result, operand *left, int shCount)
8385 {
8386     int size;
8387
8388     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8389     size = AOP_SIZE(result);
8390
8391     /* if shifting more that 3 bytes */
8392     if (shCount >= 24 ) {
8393         shCount -= 24;
8394         if (shCount)
8395             /* lowest order of left goes to the highest
8396             order of the destination */
8397             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8398         else
8399             movLeft2Result(left, LSB, result, MSB32);
8400
8401                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8402                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8403                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8404
8405         return;
8406     }
8407
8408     /* more than two bytes */
8409     else if ( shCount >= 16 ) {
8410         /* lower order two bytes goes to higher order two bytes */
8411         shCount -= 16;
8412         /* if some more remaining */
8413         if (shCount)
8414             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8415         else {
8416             movLeft2Result(left, MSB16, result, MSB32);
8417             movLeft2Result(left, LSB, result, MSB24);
8418         }
8419                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8420                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8421         return;
8422     }    
8423
8424     /* if more than 1 byte */
8425     else if ( shCount >= 8 ) {
8426         /* lower order three bytes goes to higher order  three bytes */
8427         shCount -= 8;
8428         if(size == 2){
8429             if(shCount)
8430                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8431             else
8432                 movLeft2Result(left, LSB, result, MSB16);
8433         }
8434         else{   /* size = 4 */
8435             if(shCount == 0){
8436                 movLeft2Result(left, MSB24, result, MSB32);
8437                 movLeft2Result(left, MSB16, result, MSB24);
8438                 movLeft2Result(left, LSB, result, MSB16);
8439                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8440             }
8441             else if(shCount == 1)
8442                 shiftLLong(left, result, MSB16);
8443             else{
8444                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8445                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8446                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8447                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8448             }
8449         }
8450     }
8451
8452     /* 1 <= shCount <= 7 */
8453     else if(shCount <= 3)
8454     { 
8455         shiftLLong(left, result, LSB);
8456         while(--shCount >= 1)
8457             shiftLLong(result, result, LSB);
8458     }
8459     /* 3 <= shCount <= 7, optimize */
8460     else{
8461         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8462         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8463         shiftL2Left2Result(left, LSB, result, LSB, shCount);
8464     }
8465 }
8466
8467 /*-----------------------------------------------------------------*/
8468 /* genLeftShiftLiteral - left shifting by known count              */
8469 /*-----------------------------------------------------------------*/
8470 static void genLeftShiftLiteral (operand *left,
8471                                  operand *right,
8472                                  operand *result,
8473                                  iCode *ic)
8474 {    
8475     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8476     int size;
8477
8478     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8479     pic16_freeAsmop(right,NULL,ic,TRUE);
8480
8481     pic16_aopOp(left,ic,FALSE);
8482     pic16_aopOp(result,ic,FALSE);
8483
8484     size = getSize(operandType(result));
8485
8486 #if VIEW_SIZE
8487     pic16_emitcode("; shift left ","result %d, left %d",size,
8488              AOP_SIZE(left));
8489 #endif
8490
8491     /* I suppose that the left size >= result size */
8492     if(shCount == 0){
8493         while(size--){
8494             movLeft2Result(left, size, result, size);
8495         }
8496     }
8497
8498     else if(shCount >= (size * 8))
8499         while(size--)
8500             pic16_aopPut(AOP(result),zero,size);
8501     else{
8502         switch (size) {
8503             case 1:
8504                 genlshOne (result,left,shCount);
8505                 break;
8506
8507             case 2:
8508             case 3:
8509                 genlshTwo (result,left,shCount);
8510                 break;
8511
8512             case 4:
8513                 genlshFour (result,left,shCount);
8514                 break;
8515         }
8516     }
8517     pic16_freeAsmop(left,NULL,ic,TRUE);
8518     pic16_freeAsmop(result,NULL,ic,TRUE);
8519 }
8520
8521 /*-----------------------------------------------------------------*
8522  * genMultiAsm - repeat assembly instruction for size of register.
8523  * if endian == 1, then the high byte (i.e base address + size of 
8524  * register) is used first else the low byte is used first;
8525  *-----------------------------------------------------------------*/
8526 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8527 {
8528
8529   int offset = 0;
8530
8531   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8532
8533   if(!reg)
8534     return;
8535
8536   if(!endian) {
8537     endian = 1;
8538   } else {
8539     endian = -1;
8540     offset = size-1;
8541   }
8542
8543   while(size--) {
8544     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
8545     offset += endian;
8546   }
8547
8548 }
8549 /*-----------------------------------------------------------------*/
8550 /* genLeftShift - generates code for left shifting                 */
8551 /*-----------------------------------------------------------------*/
8552 static void genLeftShift (iCode *ic)
8553 {
8554   operand *left,*right, *result;
8555   int size, offset;
8556   char *l;
8557   symbol *tlbl , *tlbl1;
8558   pCodeOp *pctemp;
8559
8560   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8561
8562   right = IC_RIGHT(ic);
8563   left  = IC_LEFT(ic);
8564   result = IC_RESULT(ic);
8565
8566   pic16_aopOp(right,ic,FALSE);
8567
8568   /* if the shift count is known then do it 
8569      as efficiently as possible */
8570   if (AOP_TYPE(right) == AOP_LIT) {
8571     genLeftShiftLiteral (left,right,result,ic);
8572     return ;
8573   }
8574
8575   /* shift count is unknown then we have to form 
8576      a loop get the loop count in B : Note: we take
8577      only the lower order byte since shifting
8578      more that 32 bits make no sense anyway, ( the
8579      largest size of an object can be only 32 bits ) */  
8580
8581     
8582   pic16_aopOp(left,ic,FALSE);
8583   pic16_aopOp(result,ic,FALSE);
8584
8585   /* now move the left to the result if they are not the
8586      same */
8587   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8588       AOP_SIZE(result) > 1) {
8589
8590     size = AOP_SIZE(result);
8591     offset=0;
8592     while (size--) {
8593       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8594       if (*l == '@' && (IS_AOP_PREG(result))) {
8595
8596         pic16_emitcode("mov","a,%s",l);
8597         pic16_aopPut(AOP(result),"a",offset);
8598       } else {
8599         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8600         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8601         //pic16_aopPut(AOP(result),l,offset);
8602       }
8603       offset++;
8604     }
8605   }
8606
8607   size = AOP_SIZE(result);
8608
8609   /* if it is only one byte then */
8610   if (size == 1) {
8611     if(optimized_for_speed) {
8612       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8613       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
8614       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
8615       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8616       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8617       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8618       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8619       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
8620       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
8621       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
8622       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8623       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8624     } else {
8625
8626       tlbl = newiTempLabel(NULL);
8627       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8628                 pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8629                 pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8630       }
8631
8632       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8633       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8634       pic16_emitpLabel(tlbl->key);
8635       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8636       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8637       emitSKPC;
8638       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8639     }
8640     goto release ;
8641   }
8642     
8643   if (pic16_sameRegs(AOP(left),AOP(result))) {
8644
8645     tlbl = newiTempLabel(NULL);
8646     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8647     genMultiAsm(POC_RRCF, result, size,1);
8648     pic16_emitpLabel(tlbl->key);
8649     genMultiAsm(POC_RLCF, result, size,0);
8650     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8651     emitSKPC;
8652     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8653     goto release;
8654   }
8655
8656   //tlbl = newiTempLabel(NULL);
8657   //offset = 0 ;   
8658   //tlbl1 = newiTempLabel(NULL);
8659
8660   //reAdjustPreg(AOP(result));    
8661     
8662   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
8663   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8664   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8665   //MOVA(l);
8666   //pic16_emitcode("add","a,acc");         
8667   //pic16_aopPut(AOP(result),"a",offset++);
8668   //while (--size) {
8669   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8670   //  MOVA(l);
8671   //  pic16_emitcode("rlc","a");         
8672   //  pic16_aopPut(AOP(result),"a",offset++);
8673   //}
8674   //reAdjustPreg(AOP(result));
8675
8676   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8677   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8678
8679
8680   tlbl = newiTempLabel(NULL);
8681   tlbl1= newiTempLabel(NULL);
8682
8683   size = AOP_SIZE(result);
8684   offset = 1;
8685
8686   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8687
8688   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8689
8690   /* offset should be 0, 1 or 3 */
8691   
8692   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8693   emitSKPNZ;
8694   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8695
8696   pic16_emitpcode(POC_MOVWF, pctemp);
8697
8698
8699   pic16_emitpLabel(tlbl->key);
8700
8701   emitCLRC;
8702   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
8703   while(--size)
8704     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
8705
8706   pic16_emitpcode(POC_DECFSZ,  pctemp);
8707   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8708   pic16_emitpLabel(tlbl1->key);
8709
8710   pic16_popReleaseTempReg(pctemp);
8711
8712
8713  release:
8714   pic16_freeAsmop (right,NULL,ic,TRUE);
8715   pic16_freeAsmop(left,NULL,ic,TRUE);
8716   pic16_freeAsmop(result,NULL,ic,TRUE);
8717 }
8718
8719 /*-----------------------------------------------------------------*/
8720 /* genrshOne - right shift a one byte quantity by known count      */
8721 /*-----------------------------------------------------------------*/
8722 static void genrshOne (operand *result, operand *left,
8723                        int shCount, int sign)
8724 {
8725     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8726     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8727 }
8728
8729 /*-----------------------------------------------------------------*/
8730 /* genrshTwo - right shift two bytes by known amount != 0          */
8731 /*-----------------------------------------------------------------*/
8732 static void genrshTwo (operand *result,operand *left,
8733                        int shCount, int sign)
8734 {
8735   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8736   /* if shCount >= 8 */
8737   if (shCount >= 8) {
8738     shCount -= 8 ;
8739     if (shCount)
8740       shiftR1Left2Result(left, MSB16, result, LSB,
8741                          shCount, sign);
8742     else
8743       movLeft2Result(left, MSB16, result, LSB);
8744
8745     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8746
8747     if(sign) {
8748       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8749       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8750     }
8751   }
8752
8753   /*  1 <= shCount <= 7 */
8754   else
8755     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
8756 }
8757
8758 /*-----------------------------------------------------------------*/
8759 /* shiftRLong - shift right one long from left to result           */
8760 /* offl = LSB or MSB16                                             */
8761 /*-----------------------------------------------------------------*/
8762 static void shiftRLong (operand *left, int offl,
8763                         operand *result, int sign)
8764 {
8765     int size = AOP_SIZE(result);
8766     int same = pic16_sameRegs(AOP(left),AOP(result));
8767     int i;
8768     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8769
8770         if (same && (offl == MSB16)) { //shift one byte right
8771                 for(i=MSB16;i<size;i++) {
8772                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8773                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8774                 }
8775         }
8776
8777     if(sign)
8778                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8779         else
8780                 emitCLRC;
8781
8782         if (same) {
8783                 if (offl == LSB)
8784                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8785         } else {
8786         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8787         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8788         }
8789
8790     if(offl == MSB16) {
8791         /* add sign of "a" */
8792         pic16_addSign(result, MSB32, sign);
8793         }
8794
8795         if (same) {
8796         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8797         } else {
8798         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8799         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8800         }
8801         
8802         if (same) {
8803         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8804         } else {
8805         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8806         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8807         }
8808
8809         if (same) {
8810         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8811         } else {
8812         if(offl == LSB){
8813                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8814                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8815         }
8816         }
8817 }
8818
8819 /*-----------------------------------------------------------------*/
8820 /* genrshFour - shift four byte by a known amount != 0             */
8821 /*-----------------------------------------------------------------*/
8822 static void genrshFour (operand *result, operand *left,
8823                         int shCount, int sign)
8824 {
8825   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8826   /* if shifting more that 3 bytes */
8827   if(shCount >= 24 ) {
8828     shCount -= 24;
8829     if(shCount)
8830       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8831     else
8832       movLeft2Result(left, MSB32, result, LSB);
8833
8834     pic16_addSign(result, MSB16, sign);
8835   }
8836   else if(shCount >= 16){
8837     shCount -= 16;
8838     if(shCount)
8839       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8840     else{
8841       movLeft2Result(left, MSB24, result, LSB);
8842       movLeft2Result(left, MSB32, result, MSB16);
8843     }
8844     pic16_addSign(result, MSB24, sign);
8845   }
8846   else if(shCount >= 8){
8847     shCount -= 8;
8848     if(shCount == 1)
8849       shiftRLong(left, MSB16, result, sign);
8850     else if(shCount == 0){
8851       movLeft2Result(left, MSB16, result, LSB);
8852       movLeft2Result(left, MSB24, result, MSB16);
8853       movLeft2Result(left, MSB32, result, MSB24);
8854       pic16_addSign(result, MSB32, sign);
8855     }
8856     else{ //shcount >= 2
8857       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8858       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8859       /* the last shift is signed */
8860       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8861       pic16_addSign(result, MSB32, sign);
8862     }
8863   }
8864   else{   /* 1 <= shCount <= 7 */
8865     if(shCount <= 2){
8866       shiftRLong(left, LSB, result, sign);
8867       if(shCount == 2)
8868         shiftRLong(result, LSB, result, sign);
8869     }
8870     else{
8871       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8872       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8873       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8874     }
8875   }
8876 }
8877
8878 /*-----------------------------------------------------------------*/
8879 /* genRightShiftLiteral - right shifting by known count            */
8880 /*-----------------------------------------------------------------*/
8881 static void genRightShiftLiteral (operand *left,
8882                                   operand *right,
8883                                   operand *result,
8884                                   iCode *ic,
8885                                   int sign)
8886 {    
8887   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8888   int lsize,res_size;
8889
8890   pic16_freeAsmop(right,NULL,ic,TRUE);
8891
8892   pic16_aopOp(left,ic,FALSE);
8893   pic16_aopOp(result,ic,FALSE);
8894
8895   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8896
8897 #if VIEW_SIZE
8898   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8899                  AOP_SIZE(left));
8900 #endif
8901
8902   lsize = pic16_getDataSize(left);
8903   res_size = pic16_getDataSize(result);
8904   /* test the LEFT size !!! */
8905
8906   /* I suppose that the left size >= result size */
8907   if(shCount == 0){
8908     while(res_size--)
8909       movLeft2Result(left, lsize, result, res_size);
8910   }
8911
8912   else if(shCount >= (lsize * 8)){
8913
8914     if(res_size == 1) {
8915       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8916       if(sign) {
8917         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8918         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8919       }
8920     } else {
8921
8922       if(sign) {
8923         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8924         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8925         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8926         while(res_size--)
8927           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8928
8929       } else {
8930
8931         while(res_size--)
8932           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8933       }
8934     }
8935   } else {
8936
8937     switch (res_size) {
8938     case 1:
8939       genrshOne (result,left,shCount,sign);
8940       break;
8941
8942     case 2:
8943       genrshTwo (result,left,shCount,sign);
8944       break;
8945
8946     case 4:
8947       genrshFour (result,left,shCount,sign);
8948       break;
8949     default :
8950       break;
8951     }
8952
8953   }
8954
8955   pic16_freeAsmop(left,NULL,ic,TRUE);
8956   pic16_freeAsmop(result,NULL,ic,TRUE);
8957 }
8958
8959 /*-----------------------------------------------------------------*/
8960 /* genSignedRightShift - right shift of signed number              */
8961 /*-----------------------------------------------------------------*/
8962 static void genSignedRightShift (iCode *ic)
8963 {
8964   operand *right, *left, *result;
8965   int size, offset;
8966   //  char *l;
8967   symbol *tlbl, *tlbl1 ;
8968   pCodeOp *pctemp;
8969
8970   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8971
8972   /* we do it the hard way put the shift count in b
8973      and loop thru preserving the sign */
8974   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8975
8976   right = IC_RIGHT(ic);
8977   left  = IC_LEFT(ic);
8978   result = IC_RESULT(ic);
8979
8980   pic16_aopOp(right,ic,FALSE);  
8981   pic16_aopOp(left,ic,FALSE);
8982   pic16_aopOp(result,ic,FALSE);
8983
8984
8985   if ( AOP_TYPE(right) == AOP_LIT) {
8986     genRightShiftLiteral (left,right,result,ic,1);
8987     return ;
8988   }
8989   /* shift count is unknown then we have to form 
8990      a loop get the loop count in B : Note: we take
8991      only the lower order byte since shifting
8992      more that 32 bits make no sense anyway, ( the
8993      largest size of an object can be only 32 bits ) */  
8994
8995   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8996   //pic16_emitcode("inc","b");
8997   //pic16_freeAsmop (right,NULL,ic,TRUE);
8998   //pic16_aopOp(left,ic,FALSE);
8999   //pic16_aopOp(result,ic,FALSE);
9000
9001   /* now move the left to the result if they are not the
9002      same */
9003   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9004       AOP_SIZE(result) > 1) {
9005
9006     size = AOP_SIZE(result);
9007     offset=0;
9008     while (size--) { 
9009       /*
9010         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9011         if (*l == '@' && IS_AOP_PREG(result)) {
9012
9013         pic16_emitcode("mov","a,%s",l);
9014         pic16_aopPut(AOP(result),"a",offset);
9015         } else
9016         pic16_aopPut(AOP(result),l,offset);
9017       */
9018       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
9019       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
9020
9021       offset++;
9022     }
9023   }
9024
9025   /* mov the highest order bit to OVR */    
9026   tlbl = newiTempLabel(NULL);
9027   tlbl1= newiTempLabel(NULL);
9028
9029   size = AOP_SIZE(result);
9030   offset = size - 1;
9031
9032   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
9033
9034   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9035
9036   /* offset should be 0, 1 or 3 */
9037   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
9038   emitSKPNZ;
9039   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9040
9041   pic16_emitpcode(POC_MOVWF, pctemp);
9042
9043
9044   pic16_emitpLabel(tlbl->key);
9045
9046   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
9047   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
9048
9049   while(--size) {
9050     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
9051   }
9052
9053   pic16_emitpcode(POC_DECFSZ,  pctemp);
9054   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9055   pic16_emitpLabel(tlbl1->key);
9056
9057   pic16_popReleaseTempReg(pctemp);
9058 #if 0
9059   size = AOP_SIZE(result);
9060   offset = size - 1;
9061   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
9062   pic16_emitcode("rlc","a");
9063   pic16_emitcode("mov","ov,c");
9064   /* if it is only one byte then */
9065   if (size == 1) {
9066     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9067     MOVA(l);
9068     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9069     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9070     pic16_emitcode("mov","c,ov");
9071     pic16_emitcode("rrc","a");
9072     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9073     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9074     pic16_aopPut(AOP(result),"a",0);
9075     goto release ;
9076   }
9077
9078   reAdjustPreg(AOP(result));
9079   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9080   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9081   pic16_emitcode("mov","c,ov");
9082   while (size--) {
9083     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9084     MOVA(l);
9085     pic16_emitcode("rrc","a");         
9086     pic16_aopPut(AOP(result),"a",offset--);
9087   }
9088   reAdjustPreg(AOP(result));
9089   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9090   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9091
9092  release:
9093 #endif
9094
9095   pic16_freeAsmop(left,NULL,ic,TRUE);
9096   pic16_freeAsmop(result,NULL,ic,TRUE);
9097   pic16_freeAsmop(right,NULL,ic,TRUE);
9098 }
9099
9100 /*-----------------------------------------------------------------*/
9101 /* genRightShift - generate code for right shifting                */
9102 /*-----------------------------------------------------------------*/
9103 static void genRightShift (iCode *ic)
9104 {
9105     operand *right, *left, *result;
9106     sym_link *letype ;
9107     int size, offset;
9108     char *l;
9109     symbol *tlbl, *tlbl1 ;
9110
9111     /* if signed then we do it the hard way preserve the
9112     sign bit moving it inwards */
9113     letype = getSpec(operandType(IC_LEFT(ic)));
9114     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9115
9116     if (!SPEC_USIGN(letype)) {
9117         genSignedRightShift (ic);
9118         return ;
9119     }
9120
9121     /* signed & unsigned types are treated the same : i.e. the
9122     signed is NOT propagated inwards : quoting from the
9123     ANSI - standard : "for E1 >> E2, is equivalent to division
9124     by 2**E2 if unsigned or if it has a non-negative value,
9125     otherwise the result is implementation defined ", MY definition
9126     is that the sign does not get propagated */
9127
9128     right = IC_RIGHT(ic);
9129     left  = IC_LEFT(ic);
9130     result = IC_RESULT(ic);
9131
9132     pic16_aopOp(right,ic,FALSE);
9133
9134     /* if the shift count is known then do it 
9135     as efficiently as possible */
9136     if (AOP_TYPE(right) == AOP_LIT) {
9137         genRightShiftLiteral (left,right,result,ic, 0);
9138         return ;
9139     }
9140
9141     /* shift count is unknown then we have to form 
9142     a loop get the loop count in B : Note: we take
9143     only the lower order byte since shifting
9144     more that 32 bits make no sense anyway, ( the
9145     largest size of an object can be only 32 bits ) */  
9146
9147     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9148     pic16_emitcode("inc","b");
9149     pic16_aopOp(left,ic,FALSE);
9150     pic16_aopOp(result,ic,FALSE);
9151
9152     /* now move the left to the result if they are not the
9153     same */
9154     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9155         AOP_SIZE(result) > 1) {
9156
9157         size = AOP_SIZE(result);
9158         offset=0;
9159         while (size--) {
9160             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9161             if (*l == '@' && IS_AOP_PREG(result)) {
9162
9163                 pic16_emitcode("mov","a,%s",l);
9164                 pic16_aopPut(AOP(result),"a",offset);
9165             } else
9166                 pic16_aopPut(AOP(result),l,offset);
9167             offset++;
9168         }
9169     }
9170
9171     tlbl = newiTempLabel(NULL);
9172     tlbl1= newiTempLabel(NULL);
9173     size = AOP_SIZE(result);
9174     offset = size - 1;
9175
9176     /* if it is only one byte then */
9177     if (size == 1) {
9178
9179       tlbl = newiTempLabel(NULL);
9180       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9181         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9182         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9183       }
9184
9185       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9186       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9187       pic16_emitpLabel(tlbl->key);
9188       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9189       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9190       emitSKPC;
9191       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9192
9193       goto release ;
9194     }
9195
9196     reAdjustPreg(AOP(result));
9197     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9198     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9199     CLRC;
9200     while (size--) {
9201         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9202         MOVA(l);
9203         pic16_emitcode("rrc","a");         
9204         pic16_aopPut(AOP(result),"a",offset--);
9205     }
9206     reAdjustPreg(AOP(result));
9207
9208     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9209     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9210
9211 release:
9212     pic16_freeAsmop(left,NULL,ic,TRUE);
9213     pic16_freeAsmop (right,NULL,ic,TRUE);
9214     pic16_freeAsmop(result,NULL,ic,TRUE);
9215 }
9216
9217
9218 void pic16_loadFSR0(operand *op)
9219 {
9220         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9221 }
9222
9223 /*-----------------------------------------------------------------*/
9224 /* genUnpackBits - generates code for unpacking bits               */
9225 /*-----------------------------------------------------------------*/
9226 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
9227 {    
9228     int shCnt ;
9229     int rlen = 0 ;
9230     sym_link *etype;
9231     int offset = 0 ;
9232
9233         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9234         etype = getSpec(operandType(result));
9235
9236         /* the following call to pic16_loadFSR0 is temporary until
9237          * optimization to handle single bit assignments is added
9238          * to the function. Until then use the old safe way! -- VR */
9239         pic16_loadFSR0( left );
9240  
9241         /* read the first byte  */
9242         switch (ptype) {
9243                 case POINTER:
9244                 case IPOINTER:
9245                 case PPOINTER:
9246                 case FPOINTER:
9247                 case GPOINTER:
9248                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9249                         break;
9250                 case CPOINTER:
9251                         pic16_emitcode("clr","a");
9252                         pic16_emitcode("movc","a","@a+dptr");
9253                         break;
9254         }
9255         
9256
9257         /* if we have bitdisplacement then it fits   */
9258         /* into this byte completely or if length is */
9259         /* less than a byte                          */
9260         if ((shCnt = SPEC_BSTR(etype)) || 
9261                 (SPEC_BLEN(etype) <= 8))  {
9262
9263                 /* shift right acc */
9264                 AccRsh(shCnt, 0);
9265
9266                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9267                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9268
9269 /* VR -- normally I would use the following, but since we use the hack,
9270  * to avoid the masking from AccRsh, why not mask it right now? */
9271
9272 /*
9273                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9274 */
9275
9276                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9277           return ;
9278         }
9279
9280
9281
9282         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9283         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9284         exit(-1);
9285
9286     /* bit field did not fit in a byte  */
9287     rlen = SPEC_BLEN(etype) - 8;
9288     pic16_aopPut(AOP(result),"a",offset++);
9289
9290     while (1)  {
9291
9292         switch (ptype) {
9293         case POINTER:
9294         case IPOINTER:
9295             pic16_emitcode("inc","%s",rname);
9296             pic16_emitcode("mov","a,@%s",rname);
9297             break;
9298             
9299         case PPOINTER:
9300             pic16_emitcode("inc","%s",rname);
9301             pic16_emitcode("movx","a,@%s",rname);
9302             break;
9303
9304         case FPOINTER:
9305             pic16_emitcode("inc","dptr");
9306             pic16_emitcode("movx","a,@dptr");
9307             break;
9308             
9309         case CPOINTER:
9310             pic16_emitcode("clr","a");
9311             pic16_emitcode("inc","dptr");
9312             pic16_emitcode("movc","a","@a+dptr");
9313             break;
9314             
9315         case GPOINTER:
9316             pic16_emitcode("inc","dptr");
9317             pic16_emitcode("lcall","__gptrget");
9318             break;
9319         }
9320
9321         rlen -= 8;            
9322         /* if we are done */
9323         if ( rlen <= 0 )
9324             break ;
9325         
9326         pic16_aopPut(AOP(result),"a",offset++);
9327                               
9328     }
9329     
9330     if (rlen) {
9331         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9332         pic16_aopPut(AOP(result),"a",offset);          
9333     }
9334     
9335     return ;
9336 }
9337
9338
9339 static void genDataPointerGet(operand *left,
9340                               operand *result,
9341                               iCode *ic)
9342 {
9343   int size, offset = 0, leoffset=0 ;
9344
9345         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9346         pic16_aopOp(result, ic, FALSE);
9347
9348         size = AOP_SIZE(result);
9349 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9350
9351
9352 #if 0
9353         /* The following tests may save a redudant movff instruction when
9354          * accessing unions */
9355          
9356         /* if they are the same */
9357         if (operandsEqu (left, result)) {
9358                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9359                 goto release;
9360         }
9361 #endif
9362
9363 #if 0
9364         /* if they are the same registers */
9365         if (pic16_sameRegs(AOP(left),AOP(result))) {
9366                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9367                 goto release;
9368         }
9369 #endif
9370
9371 #if 1
9372         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9373                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9374                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9375                 goto release;
9376         }
9377 #endif
9378
9379
9380 #if 0
9381         if ( AOP_TYPE(left) == AOP_PCODE) {
9382                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
9383                                 AOP(left)->aopu.pcop->name,
9384                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
9385                                 PCOR(AOP(left)->aopu.pcop)->instance:
9386                                 PCOI(AOP(left)->aopu.pcop)->offset);
9387         }
9388 #endif
9389
9390         if(AOP(left)->aopu.pcop->type == PO_DIR)
9391                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9392
9393         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9394
9395         while (size--) {
9396                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9397                 
9398                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9399                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9400                         mov2w(AOP(left), offset); // patch 8
9401                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9402                 } else {
9403                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9404                                 pic16_popGet(AOP(left), offset), //patch 8
9405                                 pic16_popGet(AOP(result), offset)));
9406                 }
9407
9408                 offset++;
9409                 leoffset++;
9410         }
9411
9412 release:
9413     pic16_freeAsmop(result,NULL,ic,TRUE);
9414 }
9415
9416
9417
9418 /*-----------------------------------------------------------------*/
9419 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
9420 /*-----------------------------------------------------------------*/
9421 static void genNearPointerGet (operand *left, 
9422                                operand *result, 
9423                                iCode *ic)
9424 {
9425     asmop *aop = NULL;
9426     //regs *preg = NULL ;
9427     sym_link *rtype, *retype;
9428     sym_link *ltype = operandType(left);    
9429
9430         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9431         rtype = operandType(result);
9432         retype= getSpec(rtype);
9433     
9434         pic16_aopOp(left,ic,FALSE);
9435
9436 //      pic16_DumpOp("(left)",left);
9437 //      pic16_DumpOp("(result)",result);
9438
9439         /* if left is rematerialisable and
9440          * result is not bit variable type and
9441          * the left is pointer to data space i.e
9442          * lower 128 bytes of space */
9443         if (AOP_TYPE(left) == AOP_PCODE
9444                 && !IS_BITFIELD(retype)
9445                 && DCL_TYPE(ltype) == POINTER) {
9446
9447                 genDataPointerGet (left,result,ic);
9448                 pic16_freeAsmop(left, NULL, ic, TRUE);
9449           return ;
9450         }
9451     
9452         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9453
9454         /* if the value is already in a pointer register
9455          * then don't need anything more */
9456         if (!AOP_INPREG(AOP(left))) {
9457                 /* otherwise get a free pointer register */
9458                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9459                 
9460                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9461                 if( (AOP_TYPE(left) == AOP_PCODE) 
9462                         && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9463                                 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9464                 {
9465                         if(!IS_BITFIELD(retype))
9466                                 pic16_loadFSR0( left );  // patch 10
9467                 } else {
9468                         // set up FSR0 with address from left
9469                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9470                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9471                 }
9472         }
9473 //       else
9474 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9475     
9476         pic16_aopOp (result,ic,FALSE);
9477     
9478       /* if bitfield then unpack the bits */
9479     if (IS_BITFIELD(retype)) 
9480         genUnpackBits (result, left, NULL, POINTER);
9481     else {
9482         /* we have can just get the values */
9483       int size = AOP_SIZE(result);
9484       int offset = 0;   
9485         
9486       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9487
9488
9489         /* fsr0 is loaded already -- VR */
9490 //      pic16_loadFSR0( left );
9491
9492 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9493 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9494       while(size--) {
9495
9496         if(size) {
9497                 pic16_emitpcode(POC_MOVFF,
9498                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9499                                 pic16_popGet(AOP(result), offset++)));
9500         } else {
9501                 pic16_emitpcode(POC_MOVFF,
9502                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9503                                 pic16_popGet(AOP(result), offset++)));
9504         }
9505       }
9506 #if 0
9507 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9508 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9509         if(size)
9510           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9511 #endif
9512 /*
9513         while (size--) {
9514             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9515
9516                 pic16_emitcode("mov","a,@%s",rname);
9517                 pic16_aopPut(AOP(result),"a",offset);
9518             } else {
9519                 sprintf(buffer,"@%s",rname);
9520                 pic16_aopPut(AOP(result),buffer,offset);
9521             }
9522             offset++ ;
9523             if (size)
9524                 pic16_emitcode("inc","%s",rname);
9525         }
9526 */
9527     }
9528
9529     /* now some housekeeping stuff */
9530     if (aop) {
9531         /* we had to allocate for this iCode */
9532     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9533         pic16_freeAsmop(NULL,aop,ic,TRUE);
9534     } else { 
9535         /* we did not allocate which means left
9536            already in a pointer register, then
9537            if size > 0 && this could be used again
9538            we have to point it back to where it 
9539            belongs */
9540     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9541         if (AOP_SIZE(result) > 1 &&
9542             !OP_SYMBOL(left)->remat &&
9543             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9544               ic->depth )) {
9545 //          int size = AOP_SIZE(result) - 1;
9546 //          while (size--)
9547 //              pic16_emitcode("dec","%s",rname);
9548         }
9549     }
9550
9551     /* done */
9552     pic16_freeAsmop(left,NULL,ic,TRUE);
9553     pic16_freeAsmop(result,NULL,ic,TRUE);
9554      
9555 }
9556
9557 /*-----------------------------------------------------------------*/
9558 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
9559 /*-----------------------------------------------------------------*/
9560 static void genPagedPointerGet (operand *left, 
9561                                operand *result, 
9562                                iCode *ic)
9563 {
9564     asmop *aop = NULL;
9565     regs *preg = NULL ;
9566     char *rname ;
9567     sym_link *rtype, *retype;    
9568
9569     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9570
9571     rtype = operandType(result);
9572     retype= getSpec(rtype);
9573     
9574     pic16_aopOp(left,ic,FALSE);
9575
9576   /* if the value is already in a pointer register
9577        then don't need anything more */
9578     if (!AOP_INPREG(AOP(left))) {
9579         /* otherwise get a free pointer register */
9580         aop = newAsmop(0);
9581         preg = getFreePtr(ic,&aop,FALSE);
9582         pic16_emitcode("mov","%s,%s",
9583                 preg->name,
9584                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9585         rname = preg->name ;
9586     } else
9587         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9588     
9589     pic16_freeAsmop(left,NULL,ic,TRUE);
9590     pic16_aopOp (result,ic,FALSE);
9591
9592     /* if bitfield then unpack the bits */
9593     if (IS_BITFIELD(retype)) 
9594         genUnpackBits (result,left,rname,PPOINTER);
9595     else {
9596         /* we have can just get the values */
9597         int size = AOP_SIZE(result);
9598         int offset = 0 ;        
9599         
9600         while (size--) {
9601             
9602             pic16_emitcode("movx","a,@%s",rname);
9603             pic16_aopPut(AOP(result),"a",offset);
9604             
9605             offset++ ;
9606             
9607             if (size)
9608                 pic16_emitcode("inc","%s",rname);
9609         }
9610     }
9611
9612     /* now some housekeeping stuff */
9613     if (aop) {
9614         /* we had to allocate for this iCode */
9615         pic16_freeAsmop(NULL,aop,ic,TRUE);
9616     } else { 
9617         /* we did not allocate which means left
9618            already in a pointer register, then
9619            if size > 0 && this could be used again
9620            we have to point it back to where it 
9621            belongs */
9622         if (AOP_SIZE(result) > 1 &&
9623             !OP_SYMBOL(left)->remat &&
9624             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9625               ic->depth )) {
9626             int size = AOP_SIZE(result) - 1;
9627             while (size--)
9628                 pic16_emitcode("dec","%s",rname);
9629         }
9630     }
9631
9632     /* done */
9633     pic16_freeAsmop(result,NULL,ic,TRUE);
9634     
9635         
9636 }
9637
9638 /*-----------------------------------------------------------------*/
9639 /* genFarPointerGet - gget value from far space                    */
9640 /*-----------------------------------------------------------------*/
9641 static void genFarPointerGet (operand *left,
9642                               operand *result, iCode *ic)
9643 {
9644     int size, offset ;
9645     sym_link *retype = getSpec(operandType(result));
9646
9647     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9648
9649     pic16_aopOp(left,ic,FALSE);
9650
9651     /* if the operand is already in dptr 
9652     then we do nothing else we move the value to dptr */
9653     if (AOP_TYPE(left) != AOP_STR) {
9654         /* if this is remateriazable */
9655         if (AOP_TYPE(left) == AOP_IMMD)
9656             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9657         else { /* we need to get it byte by byte */
9658             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9659             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9660             if (options.model == MODEL_FLAT24)
9661             {
9662                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9663             }
9664         }
9665     }
9666     /* so dptr know contains the address */
9667     pic16_freeAsmop(left,NULL,ic,TRUE);
9668     pic16_aopOp(result,ic,FALSE);
9669
9670     /* if bit then unpack */
9671     if (IS_BITFIELD(retype)) 
9672         genUnpackBits(result,left,"dptr",FPOINTER);
9673     else {
9674         size = AOP_SIZE(result);
9675         offset = 0 ;
9676
9677         while (size--) {
9678             pic16_emitcode("movx","a,@dptr");
9679             pic16_aopPut(AOP(result),"a",offset++);
9680             if (size)
9681                 pic16_emitcode("inc","dptr");
9682         }
9683     }
9684
9685     pic16_freeAsmop(result,NULL,ic,TRUE);
9686 }
9687 #if 0
9688 /*-----------------------------------------------------------------*/
9689 /* genCodePointerGet - get value from code space                  */
9690 /*-----------------------------------------------------------------*/
9691 static void genCodePointerGet (operand *left,
9692                                 operand *result, iCode *ic)
9693 {
9694     int size, offset ;
9695     sym_link *retype = getSpec(operandType(result));
9696
9697     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9698
9699     pic16_aopOp(left,ic,FALSE);
9700
9701     /* if the operand is already in dptr 
9702     then we do nothing else we move the value to dptr */
9703     if (AOP_TYPE(left) != AOP_STR) {
9704         /* if this is remateriazable */
9705         if (AOP_TYPE(left) == AOP_IMMD)
9706             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9707         else { /* we need to get it byte by byte */
9708             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9709             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9710             if (options.model == MODEL_FLAT24)
9711             {
9712                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9713             }
9714         }
9715     }
9716     /* so dptr know contains the address */
9717     pic16_freeAsmop(left,NULL,ic,TRUE);
9718     pic16_aopOp(result,ic,FALSE);
9719
9720     /* if bit then unpack */
9721     if (IS_BITFIELD(retype)) 
9722         genUnpackBits(result,left,"dptr",CPOINTER);
9723     else {
9724         size = AOP_SIZE(result);
9725         offset = 0 ;
9726
9727         while (size--) {
9728             pic16_emitcode("clr","a");
9729             pic16_emitcode("movc","a,@a+dptr");
9730             pic16_aopPut(AOP(result),"a",offset++);
9731             if (size)
9732                 pic16_emitcode("inc","dptr");
9733         }
9734     }
9735
9736     pic16_freeAsmop(result,NULL,ic,TRUE);
9737 }
9738 #endif
9739 /*-----------------------------------------------------------------*/
9740 /* genGenPointerGet - gget value from generic pointer space        */
9741 /*-----------------------------------------------------------------*/
9742 static void genGenPointerGet (operand *left,
9743                               operand *result, iCode *ic)
9744 {
9745   int size, offset, lit;
9746   sym_link *retype = getSpec(operandType(result));
9747
9748         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9749         pic16_aopOp(left,ic,FALSE);
9750         pic16_aopOp(result,ic,FALSE);
9751         size = AOP_SIZE(result);
9752
9753         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9754
9755         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9756
9757                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9758                 // load FSR0 from immediate
9759                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9760
9761 //              pic16_loadFSR0( left );
9762
9763                 offset = 0;
9764                 while(size--) {
9765                         if(size) {
9766                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9767                         } else {
9768                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9769                         }
9770                         offset++;
9771                 }
9772                 goto release;
9773
9774         }
9775         else { /* we need to get it byte by byte */
9776                 // set up FSR0 with address from left
9777                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9778                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9779
9780                 offset = 0 ;
9781
9782                 while(size--) {
9783                         if(size) {
9784                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9785                         } else {
9786                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9787                         }
9788                         offset++;
9789                 }
9790                 goto release;
9791         }
9792
9793   /* if bit then unpack */
9794         if (IS_BITFIELD(retype)) 
9795                 genUnpackBits(result,left,"BAD",GPOINTER);
9796
9797         release:
9798         pic16_freeAsmop(left,NULL,ic,TRUE);
9799         pic16_freeAsmop(result,NULL,ic,TRUE);
9800
9801 }
9802
9803 /*-----------------------------------------------------------------*/
9804 /* genConstPointerGet - get value from const generic pointer space */
9805 /*-----------------------------------------------------------------*/
9806 static void genConstPointerGet (operand *left,
9807                                 operand *result, iCode *ic)
9808 {
9809   //sym_link *retype = getSpec(operandType(result));
9810   // symbol *albl = newiTempLabel(NULL);        // patch 15
9811   // symbol *blbl = newiTempLabel(NULL);        //
9812   // PIC_OPCODE poc;                            // patch 15
9813   int size;
9814   int offset = 0;
9815
9816   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9817   pic16_aopOp(left,ic,FALSE);
9818   pic16_aopOp(result,ic,TRUE);
9819   size = AOP_SIZE(result);
9820
9821   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9822
9823   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9824 #if 0                                                                   // patch 15
9825   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9826   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9827   pic16_emitpLabel(albl->key);
9828
9829   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9830     
9831   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9832   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9833   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9834   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9835   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9836
9837   pic16_emitpLabel(blbl->key);
9838
9839   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9840 #endif                                                                  // patch 15
9841
9842
9843   // set up table pointer
9844   if( (AOP_TYPE(left) == AOP_PCODE) 
9845       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9846           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
9847     {
9848       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9849       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9850       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9851       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9852       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9853       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9854     }
9855   else
9856     {
9857       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9858       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9859       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9860     }
9861
9862
9863   while(size--)
9864     {
9865       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9866       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9867       offset++;
9868     }
9869     
9870   pic16_freeAsmop(left,NULL,ic,TRUE);
9871   pic16_freeAsmop(result,NULL,ic,TRUE);
9872
9873 }
9874
9875
9876 /*-----------------------------------------------------------------*/
9877 /* genPointerGet - generate code for pointer get                   */
9878 /*-----------------------------------------------------------------*/
9879 static void genPointerGet (iCode *ic)
9880 {
9881     operand *left, *result ;
9882     sym_link *type, *etype;
9883     int p_type;
9884
9885     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9886
9887     left = IC_LEFT(ic);
9888     result = IC_RESULT(ic) ;
9889
9890     /* depending on the type of pointer we need to
9891     move it to the correct pointer register */
9892     type = operandType(left);
9893     etype = getSpec(type);
9894
9895 #if 0
9896     if (IS_PTR_CONST(type))
9897 #else
9898     if (IS_CODEPTR(type))
9899 #endif
9900       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9901
9902     /* if left is of type of pointer then it is simple */
9903     if (IS_PTR(type) && !IS_FUNC(type->next)) 
9904         p_type = DCL_TYPE(type);
9905     else {
9906         /* we have to go by the storage class */
9907         p_type = PTR_TYPE(SPEC_OCLS(etype));
9908
9909         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9910
9911         if (SPEC_OCLS(etype)->codesp ) {
9912           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9913           //p_type = CPOINTER ; 
9914         }
9915         else
9916             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9917               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9918                /*p_type = FPOINTER ;*/ 
9919             else
9920                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9921                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9922 /*                  p_type = PPOINTER; */
9923                 else
9924                     if (SPEC_OCLS(etype) == idata )
9925                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9926 /*                      p_type = IPOINTER; */
9927                     else
9928                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9929 /*                      p_type = POINTER ; */
9930     }
9931
9932     /* now that we have the pointer type we assign
9933     the pointer values */
9934     switch (p_type) {
9935
9936     case POINTER:       
9937     case IPOINTER:
9938         genNearPointerGet (left,result,ic);
9939         break;
9940
9941     case PPOINTER:
9942         genPagedPointerGet(left,result,ic);
9943         break;
9944
9945     case FPOINTER:
9946         genFarPointerGet (left,result,ic);
9947         break;
9948
9949     case CPOINTER:
9950         genConstPointerGet (left,result,ic);
9951         //pic16_emitcodePointerGet (left,result,ic);
9952         break;
9953
9954     case GPOINTER:
9955 #if 0
9956       if (IS_PTR_CONST(type))
9957         genConstPointerGet (left,result,ic);
9958       else
9959 #endif
9960         genGenPointerGet (left,result,ic);
9961       break;
9962
9963     default:
9964       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9965               "genPointerGet: illegal pointer type");
9966     
9967     }
9968
9969 }
9970
9971 /*-----------------------------------------------------------------*/
9972 /* genPackBits - generates code for packed bit storage             */
9973 /*-----------------------------------------------------------------*/
9974 static void genPackBits (sym_link    *etype , operand *result,
9975                          operand *right ,
9976                          char *rname, int p_type)
9977 {
9978   int shCnt = 0 ;
9979   int offset = 0  ;
9980   int rLen = 0 ;
9981   int blen, bstr ;   
9982   char *l ;
9983
9984         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9985         blen = SPEC_BLEN(etype);
9986         bstr = SPEC_BSTR(etype);
9987
9988         if(AOP_TYPE(right) == AOP_LIT) {
9989                 if((blen == 1) && (bstr < 8)) {
9990                   unsigned long lit;
9991                         /* it is a single bit, so use the appropriate bit instructions */
9992
9993                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
9994
9995                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9996 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9997                         if((p_type == POINTER) && (result)) {
9998                                 /* workaround to reduce the extra lfsr instruction */
9999                                 if(lit) {
10000                                         pic16_emitpcode(POC_BSF,
10001                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
10002                                 } else {
10003                                         pic16_emitpcode(POC_BCF,
10004                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
10005                                 }
10006                         } else {
10007
10008                                 if(lit) {
10009                                         pic16_emitpcode(POC_BSF,
10010                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10011                                 } else {
10012                                         pic16_emitpcode(POC_BCF,
10013                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10014                                 }
10015                         }
10016         
10017                   return;
10018                 }
10019
10020                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
10021                 offset++;
10022         } else
10023                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
10024
10025         /* if the bit lenth is less than or    */
10026         /* it exactly fits a byte then         */
10027         if((shCnt=SPEC_BSTR(etype))
10028                 || SPEC_BLEN(etype) <= 8 )  {
10029
10030                 /* shift left acc */
10031                 AccLsh(shCnt);
10032
10033                 /* using PRODL as a temporary register here */
10034                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
10035
10036                 switch (p_type) {
10037                         case FPOINTER:
10038                         case POINTER:
10039                         case GPOINTER:
10040                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10041 //                              pic16_emitcode ("mov","b,a");
10042 //                              pic16_emitcode("mov","a,@%s",rname);
10043                                 break;
10044                 }
10045 #if 1
10046                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10047                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
10048                                         (unsigned char)(0xff >> (8-bstr))) ));
10049                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
10050                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10051 #endif
10052
10053           return;
10054         }
10055
10056
10057         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10058         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10059         exit(-1);
10060
10061
10062     /* if we r done */
10063     if ( SPEC_BLEN(etype) <= 8 )
10064         return ;
10065
10066     pic16_emitcode("inc","%s",rname);
10067     rLen = SPEC_BLEN(etype) ;     
10068
10069
10070
10071     /* now generate for lengths greater than one byte */
10072     while (1) {
10073
10074         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
10075
10076         rLen -= 8 ;
10077         if (rLen <= 0 )
10078             break ;
10079
10080         switch (p_type) {
10081             case POINTER:
10082                 if (*l == '@') {
10083                     MOVA(l);
10084                     pic16_emitcode("mov","@%s,a",rname);
10085                 } else
10086                     pic16_emitcode("mov","@%s,%s",rname,l);
10087                 break;
10088
10089             case FPOINTER:
10090                 MOVA(l);
10091                 pic16_emitcode("movx","@dptr,a");
10092                 break;
10093
10094             case GPOINTER:
10095                 MOVA(l);
10096                 DEBUGpic16_emitcode(";lcall","__gptrput");
10097                 break;  
10098         }   
10099         pic16_emitcode ("inc","%s",rname);
10100     }
10101
10102     MOVA(l);
10103
10104     /* last last was not complete */
10105     if (rLen)   {
10106         /* save the byte & read byte */
10107         switch (p_type) {
10108             case POINTER:
10109                 pic16_emitcode ("mov","b,a");
10110                 pic16_emitcode("mov","a,@%s",rname);
10111                 break;
10112
10113             case FPOINTER:
10114                 pic16_emitcode ("mov","b,a");
10115                 pic16_emitcode("movx","a,@dptr");
10116                 break;
10117
10118             case GPOINTER:
10119                 pic16_emitcode ("push","b");
10120                 pic16_emitcode ("push","acc");
10121                 pic16_emitcode ("lcall","__gptrget");
10122                 pic16_emitcode ("pop","b");
10123                 break;
10124         }
10125
10126         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
10127         pic16_emitcode ("orl","a,b");
10128     }
10129
10130     if (p_type == GPOINTER)
10131         pic16_emitcode("pop","b");
10132
10133     switch (p_type) {
10134
10135     case POINTER:
10136         pic16_emitcode("mov","@%s,a",rname);
10137         break;
10138         
10139     case FPOINTER:
10140         pic16_emitcode("movx","@dptr,a");
10141         break;
10142         
10143     case GPOINTER:
10144         DEBUGpic16_emitcode(";lcall","__gptrput");
10145         break;                  
10146     }
10147 }
10148 /*-----------------------------------------------------------------*/
10149 /* genDataPointerSet - remat pointer to data space                 */
10150 /*-----------------------------------------------------------------*/
10151 static void genDataPointerSet(operand *right,
10152                               operand *result,
10153                               iCode *ic)
10154 {
10155     int size, offset = 0, resoffset=0 ;
10156
10157     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10158     pic16_aopOp(right,ic,FALSE);
10159
10160     size = AOP_SIZE(right);
10161
10162 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10163
10164 #if 0
10165     if ( AOP_TYPE(result) == AOP_PCODE) {
10166       fprintf(stderr,"genDataPointerSet   %s, %d\n",
10167               AOP(result)->aopu.pcop->name,
10168                 (AOP(result)->aopu.pcop->type == PO_DIR)?
10169               PCOR(AOP(result)->aopu.pcop)->instance:
10170               PCOI(AOP(result)->aopu.pcop)->offset);
10171     }
10172 #endif
10173
10174         if(AOP(result)->aopu.pcop->type == PO_DIR)
10175                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
10176
10177         while (size--) {
10178                 if (AOP_TYPE(right) == AOP_LIT) {
10179                   unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
10180
10181                         lit = lit >> (8*offset);
10182                         if(lit&0xff) {
10183                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
10184                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
10185                         } else {
10186                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
10187                         }
10188                 } else {
10189                         mov2w(AOP(right), offset);
10190                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
10191                 }
10192                 offset++;
10193                 resoffset++;
10194         }
10195
10196     pic16_freeAsmop(right,NULL,ic,TRUE);
10197 }
10198
10199
10200
10201 /*-----------------------------------------------------------------*/
10202 /* genNearPointerSet - pic16_emitcode for near pointer put         */
10203 /*-----------------------------------------------------------------*/
10204 static void genNearPointerSet (operand *right,
10205                                operand *result, 
10206                                iCode *ic)
10207 {
10208   asmop *aop = NULL;
10209   char *l;
10210   sym_link *retype;
10211   sym_link *ptype = operandType(result);
10212   sym_link *resetype;
10213     
10214         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10215         retype= getSpec(operandType(right));
10216         resetype = getSpec(operandType(result));
10217   
10218         pic16_aopOp(result,ic,FALSE);
10219     
10220         /* if the result is rematerializable &
10221          * in data space & not a bit variable */
10222         
10223         /* and result is not a bit variable */
10224         if (AOP_TYPE(result) == AOP_PCODE
10225 //              && AOP_TYPE(result) == AOP_IMMD
10226                 && DCL_TYPE(ptype) == POINTER
10227                 && !IS_BITFIELD(retype)
10228                 && !IS_BITFIELD(resetype)) {
10229
10230                 genDataPointerSet (right,result,ic);
10231                 pic16_freeAsmop(result,NULL,ic,TRUE);
10232           return;
10233         }
10234
10235         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10236         pic16_aopOp(right,ic,FALSE);
10237         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10238
10239         /* if the value is already in a pointer register
10240          * then don't need anything more */
10241         if (!AOP_INPREG(AOP(result))) {
10242                 /* otherwise get a free pointer register */
10243                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10244
10245                 if( (AOP_TYPE(result) == AOP_PCODE) 
10246                         && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10247                                 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10248                 {
10249                   if(!IS_BITFIELD(resetype))
10250                         pic16_loadFSR0( result );  // patch 10
10251                 } else {
10252                         // set up FSR0 with address of result
10253                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10254                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10255                 }
10256
10257         }
10258 //      else
10259 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10260
10261         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10262
10263         /* if bitfield then unpack the bits */
10264         if (IS_BITFIELD(resetype)) {
10265                 genPackBits (resetype, result, right, NULL, POINTER);
10266         } else {
10267                 /* we have can just get the values */
10268           int size = AOP_SIZE(right);
10269           int offset = 0 ;    
10270
10271                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10272                 while (size--) {
10273                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10274                         if (*l == '@' ) {
10275                                 //MOVA(l);
10276                                 //pic16_emitcode("mov","@%s,a",rname);
10277                                 pic16_emitcode("movf","indf0,w ;1");
10278                         } else {
10279
10280                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
10281                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
10282                                         if (size) {                                                                     // 
10283                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
10284                                         } else {                                                                        // 
10285                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
10286                                         }                                                                               // 
10287                                 } else { // no literal                                                                  // 
10288                                         if(size) {                                                                      // 
10289                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10290                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10291                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
10292                                         } else {                                                                        // 
10293                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10294                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10295                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
10296                                         }                                                                               //
10297                                 }                                                                                       // patch 10
10298                         }
10299                         offset++;
10300                 }
10301         }
10302
10303         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10304         /* now some housekeeping stuff */
10305         if (aop) {
10306                 /* we had to allocate for this iCode */
10307                 pic16_freeAsmop(NULL,aop,ic,TRUE);
10308         } else { 
10309                 /* we did not allocate which means left
10310                  * already in a pointer register, then
10311                  * if size > 0 && this could be used again
10312                  * we have to point it back to where it 
10313                  * belongs */
10314                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10315                 if (AOP_SIZE(right) > 1
10316                         && !OP_SYMBOL(result)->remat
10317                         && ( OP_SYMBOL(result)->liveTo > ic->seq
10318                                 || ic->depth )) {
10319
10320                   int size = AOP_SIZE(right) - 1;
10321
10322                         while (size--)
10323                                 pic16_emitcode("decf","fsr0,f");
10324                         //pic16_emitcode("dec","%s",rname);
10325                 }
10326         }
10327
10328         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10329         /* done */
10330 //release:
10331         pic16_freeAsmop(right,NULL,ic,TRUE);
10332         pic16_freeAsmop(result,NULL,ic,TRUE);
10333 }
10334
10335 /*-----------------------------------------------------------------*/
10336 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
10337 /*-----------------------------------------------------------------*/
10338 static void genPagedPointerSet (operand *right,
10339                                operand *result, 
10340                                iCode *ic)
10341 {
10342     asmop *aop = NULL;
10343     regs *preg = NULL ;
10344     char *rname , *l;
10345     sym_link *retype;
10346        
10347     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10348
10349     retype= getSpec(operandType(right));
10350     
10351     pic16_aopOp(result,ic,FALSE);
10352     
10353     /* if the value is already in a pointer register
10354        then don't need anything more */
10355     if (!AOP_INPREG(AOP(result))) {
10356         /* otherwise get a free pointer register */
10357         aop = newAsmop(0);
10358         preg = getFreePtr(ic,&aop,FALSE);
10359         pic16_emitcode("mov","%s,%s",
10360                 preg->name,
10361                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10362         rname = preg->name ;
10363     } else
10364         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10365     
10366     pic16_freeAsmop(result,NULL,ic,TRUE);
10367     pic16_aopOp (right,ic,FALSE);
10368
10369     /* if bitfield then unpack the bits */
10370     if (IS_BITFIELD(retype)) 
10371         genPackBits (retype,result,right,rname,PPOINTER);
10372     else {
10373         /* we have can just get the values */
10374         int size = AOP_SIZE(right);
10375         int offset = 0 ;        
10376         
10377         while (size--) {
10378             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10379             
10380             MOVA(l);
10381             pic16_emitcode("movx","@%s,a",rname);
10382
10383             if (size)
10384                 pic16_emitcode("inc","%s",rname);
10385
10386             offset++;
10387         }
10388     }
10389     
10390     /* now some housekeeping stuff */
10391     if (aop) {
10392         /* we had to allocate for this iCode */
10393         pic16_freeAsmop(NULL,aop,ic,TRUE);
10394     } else { 
10395         /* we did not allocate which means left
10396            already in a pointer register, then
10397            if size > 0 && this could be used again
10398            we have to point it back to where it 
10399            belongs */
10400         if (AOP_SIZE(right) > 1 &&
10401             !OP_SYMBOL(result)->remat &&
10402             ( OP_SYMBOL(result)->liveTo > ic->seq ||
10403               ic->depth )) {
10404             int size = AOP_SIZE(right) - 1;
10405             while (size--)
10406                 pic16_emitcode("dec","%s",rname);
10407         }
10408     }
10409
10410     /* done */
10411     pic16_freeAsmop(right,NULL,ic,TRUE);
10412     
10413         
10414 }
10415
10416 /*-----------------------------------------------------------------*/
10417 /* genFarPointerSet - set value from far space                     */
10418 /*-----------------------------------------------------------------*/
10419 static void genFarPointerSet (operand *right,
10420                               operand *result, iCode *ic)
10421 {
10422     int size, offset ;
10423     sym_link *retype = getSpec(operandType(right));
10424
10425     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10426     pic16_aopOp(result,ic,FALSE);
10427
10428     /* if the operand is already in dptr 
10429     then we do nothing else we move the value to dptr */
10430     if (AOP_TYPE(result) != AOP_STR) {
10431         /* if this is remateriazable */
10432         if (AOP_TYPE(result) == AOP_IMMD)
10433             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10434         else { /* we need to get it byte by byte */
10435             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10436             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10437             if (options.model == MODEL_FLAT24)
10438             {
10439                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10440             }
10441         }
10442     }
10443     /* so dptr know contains the address */
10444     pic16_freeAsmop(result,NULL,ic,TRUE);
10445     pic16_aopOp(right,ic,FALSE);
10446
10447     /* if bit then unpack */
10448     if (IS_BITFIELD(retype)) 
10449         genPackBits(retype,result,right,"dptr",FPOINTER);
10450     else {
10451         size = AOP_SIZE(right);
10452         offset = 0 ;
10453
10454         while (size--) {
10455             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10456             MOVA(l);
10457             pic16_emitcode("movx","@dptr,a");
10458             if (size)
10459                 pic16_emitcode("inc","dptr");
10460         }
10461     }
10462
10463     pic16_freeAsmop(right,NULL,ic,TRUE);
10464 }
10465
10466 /*-----------------------------------------------------------------*/
10467 /* genGenPointerSet - set value from generic pointer space         */
10468 /*-----------------------------------------------------------------*/
10469 static void genGenPointerSet (operand *right,
10470                               operand *result, iCode *ic)
10471 {
10472         int i, size, offset, lit;
10473         sym_link *retype = getSpec(operandType(right));
10474
10475         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10476
10477         pic16_aopOp(result,ic,FALSE);
10478         pic16_aopOp(right,ic,FALSE);
10479         size = AOP_SIZE(right);
10480         offset = 0;
10481
10482         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10483
10484         /* if the operand is already in dptr 
10485                 then we do nothing else we move the value to dptr */
10486         if (AOP_TYPE(result) != AOP_STR) {
10487                 /* if this is remateriazable */
10488                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10489                 // WARNING: anythig until "else" is untested!
10490                 if (AOP_TYPE(result) == AOP_IMMD) {
10491                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10492                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10493                         // load FSR0 from immediate
10494                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10495                         offset = 0;
10496                         while(size--) {
10497                                 if(size) {
10498                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10499                                 } else {
10500                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10501                                 }
10502                                 offset++;
10503                         }
10504                         goto release;
10505                 }
10506                 else { /* we need to get it byte by byte */
10507                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10508                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10509
10510                         // set up FSR0 with address of result
10511                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10512                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10513
10514                         /* hack hack! see if this the FSR. If so don't load W */
10515                         if(AOP_TYPE(right) != AOP_ACC) {
10516
10517                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10518
10519                                 if(AOP_TYPE(right) == AOP_LIT)
10520                                 {
10521                                         // copy literal
10522                                         // note: pic16_popGet handles sign extension
10523                                         for(i=0;i<size;i++) {
10524                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10525                                                 if(i < size-1)
10526                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10527                                                 else
10528                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10529                                         }
10530                                 } else {
10531                                         // copy regs
10532
10533                                         for(i=0;i<size;i++) {
10534                                                 if(i < size-1)
10535                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10536                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
10537                                                 else
10538                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10539                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
10540                                         }
10541                                 }
10542                                 goto release;
10543                         } 
10544                         // right = ACC
10545                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10546                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10547                         goto release;
10548         } // if (AOP_TYPE(result) != AOP_IMMD)
10549
10550         } // if (AOP_TYPE(result) != AOP_STR)
10551         /* so dptr know contains the address */
10552
10553
10554         /* if bit then unpack */
10555         if (IS_BITFIELD(retype)) 
10556                 genPackBits(retype,result,right,"dptr",GPOINTER);
10557         else {
10558                 size = AOP_SIZE(right);
10559                 offset = 0 ;
10560
10561                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
10562
10563                 // set up FSR0 with address of result
10564                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10565                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10566         
10567                 while (size--) {
10568                         if (AOP_TYPE(right) == AOP_LIT) {
10569                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10570                                 if (size) {
10571                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10572                                 } else {
10573                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10574                                 }
10575                         } else { // no literal
10576                                 if(size) {
10577                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10578                                 } else {
10579                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10580                                 }
10581                         }
10582                         offset++;
10583                 }
10584         }
10585
10586         release:
10587         pic16_freeAsmop(right,NULL,ic,TRUE);
10588         pic16_freeAsmop(result,NULL,ic,TRUE);
10589 }
10590
10591 /*-----------------------------------------------------------------*/
10592 /* genPointerSet - stores the value into a pointer location        */
10593 /*-----------------------------------------------------------------*/
10594 static void genPointerSet (iCode *ic)
10595 {    
10596     operand *right, *result ;
10597     sym_link *type, *etype;
10598     int p_type;
10599
10600     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10601
10602     right = IC_RIGHT(ic);
10603     result = IC_RESULT(ic) ;
10604
10605     /* depending on the type of pointer we need to
10606     move it to the correct pointer register */
10607     type = operandType(result);
10608     etype = getSpec(type);
10609     /* if left is of type of pointer then it is simple */
10610     if (IS_PTR(type) && !IS_FUNC(type->next)) {
10611         p_type = DCL_TYPE(type);
10612     }
10613     else {
10614         /* we have to go by the storage class */
10615         p_type = PTR_TYPE(SPEC_OCLS(etype));
10616
10617 /*      if (SPEC_OCLS(etype)->codesp ) { */
10618 /*          p_type = CPOINTER ;  */
10619 /*      } */
10620 /*      else */
10621 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10622 /*              p_type = FPOINTER ; */
10623 /*          else */
10624 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10625 /*                  p_type = PPOINTER ; */
10626 /*              else */
10627 /*                  if (SPEC_OCLS(etype) == idata ) */
10628 /*                      p_type = IPOINTER ; */
10629 /*                  else */
10630 /*                      p_type = POINTER ; */
10631     }
10632
10633     /* now that we have the pointer type we assign
10634     the pointer values */
10635     switch (p_type) {
10636
10637     case POINTER:
10638     case IPOINTER:
10639         genNearPointerSet (right,result,ic);
10640         break;
10641
10642     case PPOINTER:
10643         genPagedPointerSet (right,result,ic);
10644         break;
10645
10646     case FPOINTER:
10647         genFarPointerSet (right,result,ic);
10648         break;
10649
10650     case GPOINTER:
10651         genGenPointerSet (right,result,ic);
10652         break;
10653
10654     default:
10655       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10656               "genPointerSet: illegal pointer type");
10657     }
10658 }
10659
10660 /*-----------------------------------------------------------------*/
10661 /* genIfx - generate code for Ifx statement                        */
10662 /*-----------------------------------------------------------------*/
10663 static void genIfx (iCode *ic, iCode *popIc)
10664 {
10665   operand *cond = IC_COND(ic);
10666   int isbit =0;
10667
10668   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10669
10670   pic16_aopOp(cond,ic,FALSE);
10671
10672   /* get the value into acc */
10673   if (AOP_TYPE(cond) != AOP_CRY)
10674     pic16_toBoolean(cond);
10675   else
10676     isbit = 1;
10677   /* the result is now in the accumulator */
10678   pic16_freeAsmop(cond,NULL,ic,TRUE);
10679
10680   /* if there was something to be popped then do it */
10681   if (popIc)
10682     genIpop(popIc);
10683
10684   /* if the condition is  a bit variable */
10685   if (isbit && IS_ITEMP(cond) && 
10686       SPIL_LOC(cond)) {
10687     genIfxJump(ic,SPIL_LOC(cond)->rname);
10688     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10689   }
10690   else {
10691     if (isbit && !IS_ITEMP(cond))
10692       genIfxJump(ic,OP_SYMBOL(cond)->rname);
10693     else
10694       genIfxJump(ic,"a");
10695   }
10696   ic->generated = 1;
10697
10698 }
10699
10700 /*-----------------------------------------------------------------*/
10701 /* genAddrOf - generates code for address of                       */
10702 /*-----------------------------------------------------------------*/
10703 static void genAddrOf (iCode *ic)
10704 {
10705   operand *result, *left;
10706   int size;
10707   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
10708   pCodeOp *pcop0, *pcop1, *pcop2;
10709
10710         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10711
10712         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10713         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10714
10715         sym = OP_SYMBOL( left );
10716
10717         size = AOP_SIZE(IC_RESULT(ic));
10718
10719
10720         if(sym->onStack) {
10721                 DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
10722         
10723                 return;
10724         }
10725         
10726 //      if(pic16_debug_verbose) {
10727 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10728 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10729 //      }
10730         
10731         /* Assume that what we want the address of is in data space
10732          * since there is no stack on the PIC, yet! -- VR */
10733         /* low */
10734         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10735
10736         /* high */
10737         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10738         
10739         /* upper */
10740         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10741         
10742
10743         if (size == 3) {
10744                 pic16_emitpcode(POC_MOVLW, pcop0);
10745                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10746                 pic16_emitpcode(POC_MOVLW, pcop1);
10747                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10748                 pic16_emitpcode(POC_MOVLW, pcop2);
10749                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10750         } else
10751         if (size == 2) {
10752                 pic16_emitpcode(POC_MOVLW, pcop0);
10753                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10754                 pic16_emitpcode(POC_MOVLW, pcop1);
10755                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10756         } else {
10757                 pic16_emitpcode(POC_MOVLW, pcop0);
10758                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10759         }
10760
10761         pic16_freeAsmop(result,NULL,ic,TRUE);
10762         pic16_freeAsmop(left, NULL, ic, FALSE);
10763 }
10764
10765
10766 #if 0
10767 /*-----------------------------------------------------------------*/
10768 /* genFarFarAssign - assignment when both are in far space         */
10769 /*-----------------------------------------------------------------*/
10770 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10771 {
10772     int size = AOP_SIZE(right);
10773     int offset = 0;
10774     char *l ;
10775     /* first push the right side on to the stack */
10776     while (size--) {
10777         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10778         MOVA(l);
10779         pic16_emitcode ("push","acc");
10780     }
10781     
10782     pic16_freeAsmop(right,NULL,ic,FALSE);
10783     /* now assign DPTR to result */
10784     pic16_aopOp(result,ic,FALSE);
10785     size = AOP_SIZE(result);
10786     while (size--) {
10787         pic16_emitcode ("pop","acc");
10788         pic16_aopPut(AOP(result),"a",--offset);
10789     }
10790     pic16_freeAsmop(result,NULL,ic,FALSE);
10791         
10792 }
10793 #endif
10794
10795 /*-----------------------------------------------------------------*/
10796 /* genAssign - generate code for assignment                        */
10797 /*-----------------------------------------------------------------*/
10798 static void genAssign (iCode *ic)
10799 {
10800   operand *result, *right;
10801   int size, offset,know_W;
10802   unsigned long lit = 0L;
10803
10804   result = IC_RESULT(ic);
10805   right  = IC_RIGHT(ic) ;
10806
10807   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10808   
10809   /* if they are the same */
10810   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10811     return ;
10812
10813   pic16_aopOp(right,ic,FALSE);
10814   pic16_aopOp(result,ic,TRUE);
10815
10816   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10817
10818   /* if they are the same registers */
10819   if (pic16_sameRegs(AOP(right),AOP(result)))
10820     goto release;
10821
10822   /* if the result is a bit */
10823   if (AOP_TYPE(result) == AOP_CRY) {
10824     /* if the right size is a literal then
10825        we know what the value is */
10826     if (AOP_TYPE(right) == AOP_LIT) {
10827           
10828       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10829                   pic16_popGet(AOP(result),0));
10830
10831       if (((int) operandLitValue(right))) 
10832         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10833                        AOP(result)->aopu.aop_dir,
10834                        AOP(result)->aopu.aop_dir);
10835       else
10836         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10837                        AOP(result)->aopu.aop_dir,
10838                        AOP(result)->aopu.aop_dir);
10839       goto release;
10840     }
10841
10842     /* the right is also a bit variable */
10843     if (AOP_TYPE(right) == AOP_CRY) {
10844       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10845       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10846       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10847
10848       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10849                      AOP(result)->aopu.aop_dir,
10850                      AOP(result)->aopu.aop_dir);
10851       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10852                      AOP(right)->aopu.aop_dir,
10853                      AOP(right)->aopu.aop_dir);
10854       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10855                      AOP(result)->aopu.aop_dir,
10856                      AOP(result)->aopu.aop_dir);
10857       goto release ;
10858     }
10859
10860     /* we need to or */
10861     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10862     pic16_toBoolean(right);
10863     emitSKPZ;
10864     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10865     //pic16_aopPut(AOP(result),"a",0);
10866     goto release ;
10867   }
10868
10869   /* bit variables done */
10870   /* general case */
10871   size = AOP_SIZE(result);
10872   offset = 0 ;
10873
10874   if(AOP_TYPE(right) == AOP_LIT) {
10875         if(!IS_FLOAT(operandType( right )))
10876                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10877         else {
10878            union {
10879               unsigned long lit_int;
10880               float lit_float;
10881             } info;
10882         
10883                 /* take care if literal is a float */
10884                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
10885                 lit = info.lit_int;
10886         }
10887   }
10888
10889 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
10890 //                      sizeof(unsigned long int), sizeof(float));
10891
10892   if(AOP_TYPE(right) != AOP_LIT
10893         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
10894         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
10895         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
10896
10897         // set up table pointer
10898         if( (AOP_TYPE(right) == AOP_PCODE)
10899                 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
10900                 || (AOP(right)->aopu.pcop->type == PO_DIR)))
10901         {
10902                 fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
10903                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
10904                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10905                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
10906                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10907                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
10908                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10909         } else {
10910                 fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
10911                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
10912                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
10913                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
10914                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
10915                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
10916                                 pic16_popCopyReg(&pic16_pc_tblptru)));
10917         }
10918
10919         size = min(AOP_SIZE(right), AOP_SIZE(result));
10920         while(size--) {
10921                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10922                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
10923                         pic16_popGet(AOP(result),offset)));
10924                 offset++;
10925         }
10926
10927         if(AOP_SIZE(result) > AOP_SIZE(right)) {
10928                 size = AOP_SIZE(result) - AOP_SIZE(right);
10929                 while(size--) {
10930                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
10931                         offset++;
10932                 }
10933         }
10934         goto release;
10935   }
10936
10937
10938
10939 #if 0
10940 /* VR - What is this?! */
10941   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10942     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10943     if(aopIdx(AOP(result),0) == 4) {
10944
10945       /* this is a workaround to save value of right into wreg too,
10946        * value of wreg is going to be used later */
10947       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10948       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10949       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10950       goto release;
10951     } else
10952 //      assert(0);
10953       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10954   }
10955 #endif
10956
10957   know_W=-1;
10958   while (size--) {
10959   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10960     if(AOP_TYPE(right) == AOP_LIT) {
10961       if(lit&0xff) {
10962         if(know_W != (lit&0xff))
10963           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10964         know_W = lit&0xff;
10965         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10966       } else
10967         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10968
10969       lit >>= 8;
10970
10971     } else if (AOP_TYPE(right) == AOP_CRY) {
10972       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10973       if(offset == 0) {
10974         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10975         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10976       }
10977     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10978         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10979         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10980     } else {
10981   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10982
10983 #if 1
10984         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10985            normally should work, but mind that the W register live range
10986            is not checked, so if the code generator assumes that the W
10987            is already loaded after such a pair, wrong code will be generated.
10988            
10989            Checking the live range is the next step.
10990            This is experimental code yet and has not been fully tested yet.
10991            USE WITH CARE. Revert to old code by setting 0 to the condition above.
10992            Vangelis Rokas 030603 (vrokas@otenet.gr) */
10993            
10994         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10995 #else   
10996         /* This is the old code, which is assumed(?!) that works fine(!?) */
10997
10998         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10999         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11000 #endif
11001     }
11002             
11003     offset++;
11004   }
11005
11006     
11007  release:
11008   pic16_freeAsmop (right,NULL,ic,FALSE);
11009   pic16_freeAsmop (result,NULL,ic,TRUE);
11010 }   
11011
11012 /*-----------------------------------------------------------------*/
11013 /* genJumpTab - generates code for jump table                       */
11014 /*-----------------------------------------------------------------*/
11015 static void genJumpTab (iCode *ic)
11016 {
11017     symbol *jtab;
11018     char *l;
11019
11020     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11021
11022     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
11023     /* get the condition into accumulator */
11024     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
11025     MOVA(l);
11026     /* multiply by three */
11027     pic16_emitcode("add","a,acc");
11028     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
11029
11030     jtab = newiTempLabel(NULL);
11031     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
11032     pic16_emitcode("jmp","@a+dptr");
11033     pic16_emitcode("","%05d_DS_:",jtab->key+100);
11034
11035     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
11036     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
11037     emitSKPNC;
11038     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
11039     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
11040     pic16_emitpLabel(jtab->key);
11041
11042     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
11043
11044     /* now generate the jump labels */
11045     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
11046          jtab = setNextItem(IC_JTLABELS(ic))) {
11047         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
11048         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
11049         
11050     }
11051
11052 }
11053
11054 /*-----------------------------------------------------------------*/
11055 /* genMixedOperation - gen code for operators between mixed types  */
11056 /*-----------------------------------------------------------------*/
11057 /*
11058   TSD - Written for the PIC port - but this unfortunately is buggy.
11059   This routine is good in that it is able to efficiently promote 
11060   types to different (larger) sizes. Unfortunately, the temporary
11061   variables that are optimized out by this routine are sometimes
11062   used in other places. So until I know how to really parse the 
11063   iCode tree, I'm going to not be using this routine :(.
11064 */
11065 static int genMixedOperation (iCode *ic)
11066 {
11067 #if 0
11068   operand *result = IC_RESULT(ic);
11069   sym_link *ctype = operandType(IC_LEFT(ic));
11070   operand *right = IC_RIGHT(ic);
11071   int ret = 0;
11072   int big,small;
11073   int offset;
11074
11075   iCode *nextic;
11076   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
11077
11078   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11079
11080   nextic = ic->next;
11081   if(!nextic)
11082     return 0;
11083
11084   nextright = IC_RIGHT(nextic);
11085   nextleft  = IC_LEFT(nextic);
11086   nextresult = IC_RESULT(nextic);
11087
11088   pic16_aopOp(right,ic,FALSE);
11089   pic16_aopOp(result,ic,FALSE);
11090   pic16_aopOp(nextright,  nextic, FALSE);
11091   pic16_aopOp(nextleft,   nextic, FALSE);
11092   pic16_aopOp(nextresult, nextic, FALSE);
11093
11094   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
11095
11096     operand *t = right;
11097     right = nextright;
11098     nextright = t; 
11099
11100     pic16_emitcode(";remove right +","");
11101
11102   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
11103 /*
11104     operand *t = right;
11105     right = nextleft;
11106     nextleft = t; 
11107 */
11108     pic16_emitcode(";remove left +","");
11109   } else
11110     return 0;
11111
11112   big = AOP_SIZE(nextleft);
11113   small = AOP_SIZE(nextright);
11114
11115   switch(nextic->op) {
11116
11117   case '+':
11118     pic16_emitcode(";optimize a +","");
11119     /* if unsigned or not an integral type */
11120     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
11121       pic16_emitcode(";add a bit to something","");
11122     } else {
11123
11124       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
11125
11126       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
11127         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
11128         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
11129       } else
11130         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
11131
11132       offset = 0;
11133       while(--big) {
11134
11135         offset++;
11136
11137         if(--small) {
11138           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11139             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11140             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11141           }
11142
11143           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11144           emitSKPNC;
11145           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11146                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
11147                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
11148           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11149           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
11150
11151         } else {
11152           pic16_emitcode("rlf","known_zero,w");
11153
11154           /*
11155             if right is signed
11156               btfsc  right,7
11157                addlw ff
11158           */
11159           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11160             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11161             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11162           } else {
11163             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11164           }
11165         }
11166       }
11167       ret = 1;
11168     }
11169   }
11170   ret = 1;
11171
11172 release:
11173   pic16_freeAsmop(right,NULL,ic,TRUE);
11174   pic16_freeAsmop(result,NULL,ic,TRUE);
11175   pic16_freeAsmop(nextright,NULL,ic,TRUE);
11176   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
11177   if(ret)
11178     nextic->generated = 1;
11179
11180   return ret;
11181 #else
11182   return 0;
11183 #endif
11184 }
11185 /*-----------------------------------------------------------------*/
11186 /* genCast - gen code for casting                                  */
11187 /*-----------------------------------------------------------------*/
11188 static void genCast (iCode *ic)
11189 {
11190   operand *result = IC_RESULT(ic);
11191   sym_link *ctype = operandType(IC_LEFT(ic));
11192   sym_link *rtype = operandType(IC_RIGHT(ic));
11193   operand *right = IC_RIGHT(ic);
11194   int size, offset ;
11195
11196         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11197         /* if they are equivalent then do nothing */
11198         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
11199                 return ;
11200
11201         pic16_aopOp(right,ic,FALSE) ;
11202         pic16_aopOp(result,ic,FALSE);
11203
11204         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11205
11206         /* if the result is a bit */
11207         if (AOP_TYPE(result) == AOP_CRY) {
11208         
11209                 /* if the right size is a literal then
11210                  * we know what the value is */
11211                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11212
11213                 if (AOP_TYPE(right) == AOP_LIT) {
11214                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
11215                                 pic16_popGet(AOP(result),0));
11216
11217                         if (((int) operandLitValue(right))) 
11218                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
11219                                         AOP(result)->aopu.aop_dir,
11220                                         AOP(result)->aopu.aop_dir);
11221                         else
11222                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
11223                                         AOP(result)->aopu.aop_dir,
11224                                         AOP(result)->aopu.aop_dir);
11225                         goto release;
11226                 }
11227
11228                 /* the right is also a bit variable */
11229                 if (AOP_TYPE(right) == AOP_CRY) {
11230                         emitCLRC;
11231                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
11232
11233                         pic16_emitcode("clrc","");
11234                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11235                                 AOP(right)->aopu.aop_dir,
11236                                 AOP(right)->aopu.aop_dir);
11237                         pic16_aopPut(AOP(result),"c",0);
11238                         goto release ;
11239                 }
11240
11241                 /* we need to or */
11242                 if (AOP_TYPE(right) == AOP_REG) {
11243                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
11244                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
11245                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
11246                 }
11247                 pic16_toBoolean(right);
11248                 pic16_aopPut(AOP(result),"a",0);
11249                 goto release ;
11250         }
11251
11252         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
11253           int offset = 1;
11254
11255                 size = AOP_SIZE(result);
11256
11257                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11258
11259                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
11260                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
11261                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
11262
11263                 while (size--)
11264                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11265
11266                 goto release;
11267         }
11268
11269         /* if they are the same size : or less */
11270         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
11271
11272                 /* if they are in the same place */
11273                 if (pic16_sameRegs(AOP(right),AOP(result)))
11274                         goto release;
11275
11276                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11277 #if 0
11278                 if (IS_PTR_CONST(rtype))
11279 #else
11280                 if (IS_CODEPTR(rtype))
11281 #endif
11282                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
11283
11284 #if 0
11285                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
11286 #else
11287                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
11288 #endif
11289                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
11290
11291 #if 0
11292                 if(AOP_TYPE(right) == AOP_IMMD) {
11293                   pCodeOp *pcop0, *pcop1, *pcop2;
11294                   symbol *sym = OP_SYMBOL( right );
11295
11296                         size = AOP_SIZE(result);
11297                         /* low */
11298                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11299                         /* high */
11300                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11301                         /* upper */
11302                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11303         
11304                         if (size == 3) {
11305                                 pic16_emitpcode(POC_MOVLW, pcop0);
11306                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11307                                 pic16_emitpcode(POC_MOVLW, pcop1);
11308                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11309                                 pic16_emitpcode(POC_MOVLW, pcop2);
11310                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11311                         } else
11312                         if (size == 2) {
11313                                 pic16_emitpcode(POC_MOVLW, pcop0);
11314                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11315                                 pic16_emitpcode(POC_MOVLW, pcop1);
11316                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11317                         } else {
11318                                 pic16_emitpcode(POC_MOVLW, pcop0);
11319                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11320                         }
11321                 } else
11322 #endif
11323                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11324                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
11325                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11326                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
11327                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11328                         if(AOP_SIZE(result) <2)
11329                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
11330                 } else {
11331                         /* if they in different places then copy */
11332                         size = AOP_SIZE(result);
11333                         offset = 0 ;
11334                         while (size--) {
11335                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11336                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11337                                 offset++;
11338                         }
11339                 }
11340                 goto release;
11341         }
11342
11343         /* if the result is of type pointer */
11344         if (IS_PTR(ctype)) {
11345           int p_type;
11346           sym_link *type = operandType(right);
11347           sym_link *etype = getSpec(type);
11348
11349                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
11350
11351                 /* pointer to generic pointer */
11352                 if (IS_GENPTR(ctype)) {
11353                   char *l = zero;
11354             
11355                         if (IS_PTR(type)) 
11356                                 p_type = DCL_TYPE(type);
11357                         else {
11358                 /* we have to go by the storage class */
11359                 p_type = PTR_TYPE(SPEC_OCLS(etype));
11360
11361 /*              if (SPEC_OCLS(etype)->codesp )  */
11362 /*                  p_type = CPOINTER ;  */
11363 /*              else */
11364 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11365 /*                      p_type = FPOINTER ; */
11366 /*                  else */
11367 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11368 /*                          p_type = PPOINTER; */
11369 /*                      else */
11370 /*                          if (SPEC_OCLS(etype) == idata ) */
11371 /*                              p_type = IPOINTER ; */
11372 /*                          else */
11373 /*                              p_type = POINTER ; */
11374             }
11375                 
11376             /* the first two bytes are known */
11377       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
11378             size = GPTRSIZE - 1; 
11379             offset = 0 ;
11380             while (size--) {
11381               if(offset < AOP_SIZE(right)) {
11382       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
11383                 if ((AOP_TYPE(right) == AOP_PCODE) && 
11384                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11385                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11386                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11387                 } else { 
11388                   pic16_aopPut(AOP(result),
11389                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11390                          offset);
11391                 }
11392               } else 
11393                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11394               offset++;
11395             }
11396             /* the last byte depending on type */
11397             switch (p_type) {
11398             case IPOINTER:
11399             case POINTER:
11400                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11401                 break;
11402             case FPOINTER:
11403               pic16_emitcode(";BUG!? ","%d",__LINE__);
11404                 l = one;
11405                 break;
11406             case CPOINTER:
11407               pic16_emitcode(";BUG!? ","%d",__LINE__);
11408                 l = "#0x02";
11409                 break;                          
11410             case PPOINTER:
11411               pic16_emitcode(";BUG!? ","%d",__LINE__);
11412                 l = "#0x03";
11413                 break;
11414                 
11415             default:
11416                 /* this should never happen */
11417                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11418                        "got unknown pointer type");
11419                 exit(1);
11420             }
11421             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
11422             goto release ;
11423         }
11424         
11425         /* just copy the pointers */
11426         size = AOP_SIZE(result);
11427         offset = 0 ;
11428         while (size--) {
11429             pic16_aopPut(AOP(result),
11430                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11431                    offset);
11432             offset++;
11433         }
11434         goto release ;
11435     }
11436     
11437
11438
11439     /* so we now know that the size of destination is greater
11440     than the size of the source.
11441     Now, if the next iCode is an operator then we might be
11442     able to optimize the operation without performing a cast.
11443     */
11444     if(genMixedOperation(ic))
11445       goto release;
11446
11447     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11448     
11449     /* we move to result for the size of source */
11450     size = AOP_SIZE(right);
11451     offset = 0 ;
11452     while (size--) {
11453       pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
11454 //      pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
11455 //      pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
11456       offset++;
11457     }
11458
11459     /* now depending on the sign of the destination */
11460     size = AOP_SIZE(result) - AOP_SIZE(right);
11461     /* if unsigned or not an integral type */
11462     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11463       while (size--)
11464         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11465     } else {
11466       /* we need to extend the sign :( */
11467
11468       if(size == 1) {
11469         /* Save one instruction of casting char to int */
11470         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
11471         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11472         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
11473       } else {
11474         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11475
11476         if(offset)
11477           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11478         else
11479           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11480         
11481         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
11482
11483         while (size--)
11484           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
11485       }
11486     }
11487
11488 release:
11489     pic16_freeAsmop(right,NULL,ic,TRUE);
11490     pic16_freeAsmop(result,NULL,ic,TRUE);
11491
11492 }
11493
11494 /*-----------------------------------------------------------------*/
11495 /* genDjnz - generate decrement & jump if not zero instrucion      */
11496 /*-----------------------------------------------------------------*/
11497 static int genDjnz (iCode *ic, iCode *ifx)
11498 {
11499     symbol *lbl, *lbl1;
11500     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11501
11502     if (!ifx)
11503         return 0;
11504     
11505     /* if the if condition has a false label
11506        then we cannot save */
11507     if (IC_FALSE(ifx))
11508         return 0;
11509
11510     /* if the minus is not of the form 
11511        a = a - 1 */
11512     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11513         !IS_OP_LITERAL(IC_RIGHT(ic)))
11514         return 0;
11515
11516     if (operandLitValue(IC_RIGHT(ic)) != 1)
11517         return 0;
11518
11519     /* if the size of this greater than one then no
11520        saving */
11521     if (getSize(operandType(IC_RESULT(ic))) > 1)
11522         return 0;
11523
11524     /* otherwise we can save BIG */
11525     lbl = newiTempLabel(NULL);
11526     lbl1= newiTempLabel(NULL);
11527
11528     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11529     
11530     if (IS_AOP_PREG(IC_RESULT(ic))) {
11531         pic16_emitcode("dec","%s",
11532                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11533         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11534         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11535     } else {    
11536
11537
11538       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11539       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11540
11541       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11542       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
11543
11544     }
11545 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11546 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11547 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11548 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11549
11550     
11551     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11552     ifx->generated = 1;
11553     return 1;
11554 }
11555
11556 /*-----------------------------------------------------------------*/
11557 /* genReceive - generate code for a receive iCode                  */
11558 /*-----------------------------------------------------------------*/
11559 static void genReceive (iCode *ic)
11560 {    
11561         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11562
11563 #if 0
11564         fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
11565                 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
11566 #endif
11567 //      pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
11568
11569         if (isOperandInFarSpace(IC_RESULT(ic)) &&
11570                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11571                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11572
11573           int size = getSize(operandType(IC_RESULT(ic)));
11574           int offset =  pic16_fReturnSizePic - size;
11575
11576                 assert( 0 );
11577                 while (size--) {
11578                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11579                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11580                         offset++;
11581                 }
11582
11583                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
11584
11585                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11586                 size = AOP_SIZE(IC_RESULT(ic));
11587                 offset = 0;
11588                 while (size--) {
11589                         pic16_emitcode ("pop","acc");
11590                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11591                 }
11592         } else {
11593                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
11594
11595                 _G.accInUse++;
11596                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11597                 _G.accInUse--;
11598                 assignResultValue(IC_RESULT(ic), 0);
11599         }
11600
11601         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11602 }
11603
11604 /*-----------------------------------------------------------------*/
11605 /* genDummyRead - generate code for dummy read of volatiles        */
11606 /*-----------------------------------------------------------------*/
11607 static void
11608 genDummyRead (iCode * ic)
11609 {
11610   pic16_emitcode ("; genDummyRead","");
11611   pic16_emitcode ("; not implemented","");
11612
11613   ic = ic;
11614 }
11615
11616 /*-----------------------------------------------------------------*/
11617 /* genpic16Code - generate code for pic16 based controllers        */
11618 /*-----------------------------------------------------------------*/
11619 /*
11620  * At this point, ralloc.c has gone through the iCode and attempted
11621  * to optimize in a way suitable for a PIC. Now we've got to generate
11622  * PIC instructions that correspond to the iCode.
11623  *
11624  * Once the instructions are generated, we'll pass through both the
11625  * peep hole optimizer and the pCode optimizer.
11626  *-----------------------------------------------------------------*/
11627
11628 void genpic16Code (iCode *lic)
11629 {
11630     iCode *ic;
11631     int cln = 0;
11632
11633     lineHead = lineCurr = NULL;
11634
11635     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11636     pic16_addpBlock(pb);
11637
11638 #if 0
11639     /* if debug information required */
11640     if (options.debug && currFunc) {
11641       if (currFunc) {
11642         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11643       }
11644     }
11645 #endif
11646
11647     for (ic = lic ; ic ; ic = ic->next ) {
11648
11649       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11650         if ( cln != ic->lineno ) {
11651             if ( options.debug ) {
11652               debugFile->writeCLine (ic);
11653             }
11654             
11655             if(!options.noCcodeInAsm) {
11656                 pic16_addpCode2pBlock(pb,
11657                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
11658                                 printCLine(ic->filename, ic->lineno)));
11659             }
11660
11661             cln = ic->lineno ;
11662         }
11663         
11664         if(options.iCodeInAsm) {
11665                 char *l;
11666                 /* insert here code to print iCode as comment */
11667                 l = Safe_strdup(printILine(ic));
11668                 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11669         }
11670         
11671         /* if the result is marked as
11672            spilt and rematerializable or code for
11673            this has already been generated then
11674            do nothing */
11675         if (resultRemat(ic) || ic->generated ) 
11676             continue ;
11677         
11678         /* depending on the operation */
11679         switch (ic->op) {
11680         case '!' :
11681             pic16_genNot(ic);
11682             break;
11683             
11684         case '~' :
11685             pic16_genCpl(ic);
11686             break;
11687             
11688         case UNARYMINUS:
11689             genUminus (ic);
11690             break;
11691             
11692         case IPUSH:
11693             genIpush (ic);
11694             break;
11695             
11696         case IPOP:
11697             /* IPOP happens only when trying to restore a 
11698                spilt live range, if there is an ifx statement
11699                following this pop then the if statement might
11700                be using some of the registers being popped which
11701                would destroy the contents of the register so
11702                we need to check for this condition and handle it */
11703             if (ic->next            && 
11704                 ic->next->op == IFX &&
11705                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
11706                 genIfx (ic->next,ic);
11707             else
11708                 genIpop (ic);
11709             break; 
11710             
11711         case CALL:
11712             genCall (ic);
11713             break;
11714             
11715         case PCALL:
11716             genPcall (ic);
11717             break;
11718             
11719         case FUNCTION:
11720             genFunction (ic);
11721             break;
11722             
11723         case ENDFUNCTION:
11724             genEndFunction (ic);
11725             break;
11726             
11727         case RETURN:
11728             genRet (ic);
11729             break;
11730             
11731         case LABEL:
11732             genLabel (ic);
11733             break;
11734             
11735         case GOTO:
11736             genGoto (ic);
11737             break;
11738             
11739         case '+' :
11740             pic16_genPlus (ic) ;
11741             break;
11742             
11743         case '-' :
11744             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11745                 pic16_genMinus (ic);
11746             break;
11747             
11748         case '*' :
11749             genMult (ic);
11750             break;
11751             
11752         case '/' :
11753             genDiv (ic) ;
11754             break;
11755             
11756         case '%' :
11757             genMod (ic);
11758             break;
11759             
11760         case '>' :
11761             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
11762             break;
11763             
11764         case '<' :
11765             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11766             break;
11767             
11768         case LE_OP:
11769         case GE_OP:
11770         case NE_OP:
11771             
11772             /* note these two are xlated by algebraic equivalence
11773                during parsing SDCC.y */
11774             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11775                    "got '>=' or '<=' shouldn't have come here");
11776             break;      
11777             
11778         case EQ_OP:
11779             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11780             break;          
11781             
11782         case AND_OP:
11783             genAndOp (ic);
11784             break;
11785             
11786         case OR_OP:
11787             genOrOp (ic);
11788             break;
11789             
11790         case '^' :
11791             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11792             break;
11793             
11794         case '|' :
11795                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11796             break;
11797             
11798         case BITWISEAND:
11799             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11800             break;
11801             
11802         case INLINEASM:
11803             genInline (ic);
11804             break;
11805             
11806         case RRC:
11807             genRRC (ic);
11808             break;
11809             
11810         case RLC:
11811             genRLC (ic);
11812             break;
11813             
11814         case GETHBIT:
11815             genGetHbit (ic);
11816             break;
11817             
11818         case LEFT_OP:
11819             genLeftShift (ic);
11820             break;
11821             
11822         case RIGHT_OP:
11823             genRightShift (ic);
11824             break;
11825             
11826         case GET_VALUE_AT_ADDRESS:
11827             genPointerGet(ic);
11828             break;
11829             
11830         case '=' :
11831             if (POINTER_SET(ic))
11832                 genPointerSet(ic);
11833             else
11834                 genAssign(ic);
11835             break;
11836             
11837         case IFX:
11838             genIfx (ic,NULL);
11839             break;
11840             
11841         case ADDRESS_OF:
11842             genAddrOf (ic);
11843             break;
11844             
11845         case JUMPTABLE:
11846             genJumpTab (ic);
11847             break;
11848             
11849         case CAST:
11850             genCast (ic);
11851             break;
11852             
11853         case RECEIVE:
11854             genReceive(ic);
11855             break;
11856             
11857         case SEND:
11858             addSet(&_G.sendSet,ic);
11859             break;
11860
11861         case DUMMY_READ_VOLATILE:
11862           genDummyRead (ic);
11863           break;
11864
11865         default :
11866             ic = ic;
11867         }
11868     }
11869
11870
11871     /* now we are ready to call the
11872        peep hole optimizer */
11873     if (!options.nopeep) {
11874       peepHole (&lineHead);
11875     }
11876     /* now do the actual printing */
11877     printLine (lineHead,codeOutFile);
11878
11879 #ifdef PCODE_DEBUG
11880     DFPRINTF((stderr,"printing pBlock\n\n"));
11881     pic16_printpBlock(stdout,pb);
11882 #endif
11883
11884     return;
11885 }
11886