* src/pic16/device.h (pic16_options_t): added 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       /* here to add patch from Aaron */
6609       if(size)
6610         emitSETC;                       //pic16_emitcode("setb","c");
6611
6612
6613       while(sizel--) {
6614         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6615
6616
6617           /* patch provided by Aaron Colwell */
6618           if((posbit = isLiteralBit(bytelit)) != 0) {
6619               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
6620                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left),
6621                                                 offset,FALSE,
6622                                                 FALSE),
6623                                                 (posbit-1),0, PO_GPR_REGISTER));
6624
6625               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
6626           } else {
6627               if (bytelit == 0xff) {
6628                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
6629                    * a peephole could optimize it out -- VR */
6630                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6631               } else {
6632                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6633                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
6634               }
6635
6636               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
6637                             pic16_popGetLabel(tlbl->key));
6638           }
6639         
6640 #if 0
6641           /* old code, left here for reference -- VR 09/2004 */
6642           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6643           // byte ==  2^n ?
6644           if((posbit = isLiteralBit(bytelit)) != 0)
6645             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6646           else{
6647             if(bytelit != 0x0FFL)
6648               pic16_emitcode("anl","a,%s",
6649                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6650             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6651           }
6652 #endif
6653         }
6654         offset++;
6655       }
6656       // bit = left & literal
6657       if(size) {
6658         emitCLRC;
6659         pic16_emitpLabel(tlbl->key);
6660       }
6661       // if(left & literal)
6662       else {
6663         if(ifx) {
6664           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
6665           pic16_emitpLabel(tlbl->key);
6666           ifx->generated = 1;
6667         }
6668         goto release;
6669       }
6670     }
6671
6672     pic16_outBitC(result);
6673     goto release ;
6674   }
6675
6676   /* if left is same as result */
6677   if(pic16_sameRegs(AOP(result),AOP(left))){
6678     int know_W = -1;
6679     for(;size--; offset++,lit>>=8) {
6680       if(AOP_TYPE(right) == AOP_LIT){
6681         switch(lit & 0xff) {
6682         case 0x00:
6683           /*  and'ing with 0 has clears the result */
6684 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6685           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6686           break;
6687         case 0xff:
6688           /* and'ing with 0xff is a nop when the result and left are the same */
6689           break;
6690
6691         default:
6692           {
6693             int p = my_powof2( (~lit) & 0xff );
6694             if(p>=0) {
6695               /* only one bit is set in the literal, so use a bcf instruction */
6696 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6697               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6698
6699             } else {
6700               pic16_emitcode("movlw","0x%x", (lit & 0xff));
6701               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6702               if(know_W != (lit&0xff))
6703                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6704               know_W = lit &0xff;
6705               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6706             }
6707           }    
6708         }
6709       } else {
6710         if (AOP_TYPE(left) == AOP_ACC) {
6711           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6712         } else {                    
6713           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6714           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6715
6716         }
6717       }
6718     }
6719
6720   } else {
6721     // left & result in different registers
6722     if(AOP_TYPE(result) == AOP_CRY){
6723       // result = bit
6724       // if(size), result in bit
6725       // if(!size && ifx), conditional oper: if(left & right)
6726       symbol *tlbl = newiTempLabel(NULL);
6727       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6728       if(size)
6729         pic16_emitcode("setb","c");
6730       while(sizer--){
6731         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6732         pic16_emitcode("anl","a,%s",
6733                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6734         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6735         offset++;
6736       }
6737       if(size){
6738         CLRC;
6739         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6740         pic16_outBitC(result);
6741       } else if(ifx)
6742         jmpTrueOrFalse(ifx, tlbl);
6743     } else {
6744       for(;(size--);offset++) {
6745         // normal case
6746         // result = left & right
6747         if(AOP_TYPE(right) == AOP_LIT){
6748           int t = (lit >> (offset*8)) & 0x0FFL;
6749           switch(t) { 
6750           case 0x00:
6751             pic16_emitcode("clrf","%s",
6752                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6753             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6754             break;
6755           case 0xff:
6756             pic16_emitcode("movf","%s,w",
6757                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6758             pic16_emitcode("movwf","%s",
6759                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6760             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6761             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6762             break;
6763           default:
6764             pic16_emitcode("movlw","0x%x",t);
6765             pic16_emitcode("andwf","%s,w",
6766                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6767             pic16_emitcode("movwf","%s",
6768                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6769               
6770             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6771             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6772             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6773           }
6774           continue;
6775         }
6776
6777         if (AOP_TYPE(left) == AOP_ACC) {
6778           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6779           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6780         } else {
6781           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6782           pic16_emitcode("andwf","%s,w",
6783                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6784           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6785           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6786         }
6787         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6788         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6789       }
6790     }
6791   }
6792
6793   release :
6794     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6795   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6796   pic16_freeAsmop(result,NULL,ic,TRUE);     
6797 }
6798
6799 /*-----------------------------------------------------------------*/
6800 /* genOr  - code for or                                            */
6801 /*-----------------------------------------------------------------*/
6802 static void genOr (iCode *ic, iCode *ifx)
6803 {
6804     operand *left, *right, *result;
6805     int size, offset=0;
6806     unsigned long lit = 0L;
6807
6808     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6809
6810     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6811     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6812     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6813
6814     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6815
6816     /* if left is a literal & right is not then exchange them */
6817     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6818         AOP_NEEDSACC(left)) {
6819         operand *tmp = right ;
6820         right = left;
6821         left = tmp;
6822     }
6823
6824     /* if result = right then exchange them */
6825     if(pic16_sameRegs(AOP(result),AOP(right))){
6826         operand *tmp = right ;
6827         right = left;
6828         left = tmp;
6829     }
6830
6831     /* if right is bit then exchange them */
6832     if (AOP_TYPE(right) == AOP_CRY &&
6833         AOP_TYPE(left) != AOP_CRY){
6834         operand *tmp = right ;
6835         right = left;
6836         left = tmp;
6837     }
6838
6839     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6840
6841     if(AOP_TYPE(right) == AOP_LIT)
6842         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6843
6844     size = AOP_SIZE(result);
6845
6846     // if(bit | yy)
6847     // xx = bit | yy;
6848     if (AOP_TYPE(left) == AOP_CRY){
6849         if(AOP_TYPE(right) == AOP_LIT){
6850             // c = bit & literal;
6851             if(lit){
6852                 // lit != 0 => result = 1
6853                 if(AOP_TYPE(result) == AOP_CRY){
6854                   if(size)
6855                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6856                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6857                   //     AOP(result)->aopu.aop_dir,
6858                   //     AOP(result)->aopu.aop_dir);
6859                     else if(ifx)
6860                         continueIfTrue(ifx);
6861                     goto release;
6862                 }
6863             } else {
6864                 // lit == 0 => result = left
6865                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6866                     goto release;
6867                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6868             }
6869         } else {
6870             if (AOP_TYPE(right) == AOP_CRY){
6871               if(pic16_sameRegs(AOP(result),AOP(left))){
6872                 // c = bit | bit;
6873                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6874                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6875                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6876
6877                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6878                          AOP(result)->aopu.aop_dir,
6879                          AOP(result)->aopu.aop_dir);
6880                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6881                          AOP(right)->aopu.aop_dir,
6882                          AOP(right)->aopu.aop_dir);
6883                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6884                          AOP(result)->aopu.aop_dir,
6885                          AOP(result)->aopu.aop_dir);
6886               } else {
6887                 if( AOP_TYPE(result) == AOP_ACC) {
6888                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6889                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6890                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6891                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6892
6893                 } else {
6894
6895                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6896                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6897                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6898                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6899
6900                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6901                                  AOP(result)->aopu.aop_dir,
6902                                  AOP(result)->aopu.aop_dir);
6903                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6904                                  AOP(right)->aopu.aop_dir,
6905                                  AOP(right)->aopu.aop_dir);
6906                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6907                                  AOP(left)->aopu.aop_dir,
6908                                  AOP(left)->aopu.aop_dir);
6909                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6910                                  AOP(result)->aopu.aop_dir,
6911                                  AOP(result)->aopu.aop_dir);
6912                 }
6913               }
6914             } else {
6915                 // c = bit | val;
6916                 symbol *tlbl = newiTempLabel(NULL);
6917                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6918
6919
6920                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6921                 if( AOP_TYPE(right) == AOP_ACC) {
6922                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6923                   emitSKPNZ;
6924                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6925                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6926                 }
6927
6928
6929
6930                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6931                     pic16_emitcode(";XXX setb","c");
6932                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6933                          AOP(left)->aopu.aop_dir,tlbl->key+100);
6934                 pic16_toBoolean(right);
6935                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6936                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6937                     jmpTrueOrFalse(ifx, tlbl);
6938                     goto release;
6939                 } else {
6940                     CLRC;
6941                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6942                 }
6943             }
6944         }
6945         // bit = c
6946         // val = c
6947         if(size)
6948             pic16_outBitC(result);
6949         // if(bit | ...)
6950         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6951             genIfxJump(ifx, "c");           
6952         goto release ;
6953     }
6954
6955     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6956     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6957     if((AOP_TYPE(right) == AOP_LIT) &&
6958        (AOP_TYPE(result) == AOP_CRY) &&
6959        (AOP_TYPE(left) != AOP_CRY)){
6960         if(lit){
6961           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6962             // result = 1
6963             if(size)
6964                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6965             else 
6966                 continueIfTrue(ifx);
6967             goto release;
6968         } else {
6969           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6970             // lit = 0, result = boolean(left)
6971             if(size)
6972                 pic16_emitcode(";XXX setb","c");
6973             pic16_toBoolean(right);
6974             if(size){
6975                 symbol *tlbl = newiTempLabel(NULL);
6976                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6977                 CLRC;
6978                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6979             } else {
6980                 genIfxJump (ifx,"a");
6981                 goto release;
6982             }
6983         }
6984         pic16_outBitC(result);
6985         goto release ;
6986     }
6987
6988     /* if left is same as result */
6989     if(pic16_sameRegs(AOP(result),AOP(left))){
6990       int know_W = -1;
6991       for(;size--; offset++,lit>>=8) {
6992         if(AOP_TYPE(right) == AOP_LIT){
6993           if((lit & 0xff) == 0)
6994             /*  or'ing with 0 has no effect */
6995             continue;
6996           else {
6997             int p = my_powof2(lit & 0xff);
6998             if(p>=0) {
6999               /* only one bit is set in the literal, so use a bsf instruction */
7000               pic16_emitpcode(POC_BSF,
7001                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7002             } else {
7003               if(know_W != (lit & 0xff))
7004                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7005               know_W = lit & 0xff;
7006               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7007             }
7008                     
7009           }
7010         } else {
7011           if (AOP_TYPE(left) == AOP_ACC) {
7012             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7013             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7014           } else {                  
7015             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7016             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7017
7018             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7019             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7020
7021           }
7022         }
7023       }
7024     } else {
7025         // left & result in different registers
7026         if(AOP_TYPE(result) == AOP_CRY){
7027             // result = bit
7028             // if(size), result in bit
7029             // if(!size && ifx), conditional oper: if(left | right)
7030             symbol *tlbl = newiTempLabel(NULL);
7031             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7032             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7033
7034
7035             if(size)
7036                 pic16_emitcode(";XXX setb","c");
7037             while(sizer--){
7038                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7039                 pic16_emitcode(";XXX orl","a,%s",
7040                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7041                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7042                 offset++;
7043             }
7044             if(size){
7045                 CLRC;
7046                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7047                 pic16_outBitC(result);
7048             } else if(ifx)
7049                 jmpTrueOrFalse(ifx, tlbl);
7050         } else for(;(size--);offset++){
7051           // normal case
7052           // result = left & right
7053           if(AOP_TYPE(right) == AOP_LIT){
7054             int t = (lit >> (offset*8)) & 0x0FFL;
7055             switch(t) { 
7056             case 0x00:
7057               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7058               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7059
7060               pic16_emitcode("movf","%s,w",
7061                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7062               pic16_emitcode("movwf","%s",
7063                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7064               break;
7065             default:
7066               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7067               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7068               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7069
7070               pic16_emitcode("movlw","0x%x",t);
7071               pic16_emitcode("iorwf","%s,w",
7072                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7073               pic16_emitcode("movwf","%s",
7074                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7075               
7076             }
7077             continue;
7078           }
7079
7080           // faster than result <- left, anl result,right
7081           // and better if result is SFR
7082           if (AOP_TYPE(left) == AOP_ACC) {
7083             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7084             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7085           } else {
7086             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7087             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7088
7089             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7090             pic16_emitcode("iorwf","%s,w",
7091                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7092           }
7093           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7094           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7095         }
7096     }
7097
7098 release :
7099     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7100     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7101     pic16_freeAsmop(result,NULL,ic,TRUE);     
7102 }
7103
7104 /*-----------------------------------------------------------------*/
7105 /* genXor - code for xclusive or                                   */
7106 /*-----------------------------------------------------------------*/
7107 static void genXor (iCode *ic, iCode *ifx)
7108 {
7109   operand *left, *right, *result;
7110   int size, offset=0;
7111   unsigned long lit = 0L;
7112
7113   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7114
7115   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7116   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7117   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7118
7119   /* if left is a literal & right is not ||
7120      if left needs acc & right does not */
7121   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7122       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7123     operand *tmp = right ;
7124     right = left;
7125     left = tmp;
7126   }
7127
7128   /* if result = right then exchange them */
7129   if(pic16_sameRegs(AOP(result),AOP(right))){
7130     operand *tmp = right ;
7131     right = left;
7132     left = tmp;
7133   }
7134
7135   /* if right is bit then exchange them */
7136   if (AOP_TYPE(right) == AOP_CRY &&
7137       AOP_TYPE(left) != AOP_CRY){
7138     operand *tmp = right ;
7139     right = left;
7140     left = tmp;
7141   }
7142   if(AOP_TYPE(right) == AOP_LIT)
7143     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7144
7145   size = AOP_SIZE(result);
7146
7147   // if(bit ^ yy)
7148   // xx = bit ^ yy;
7149   if (AOP_TYPE(left) == AOP_CRY){
7150     if(AOP_TYPE(right) == AOP_LIT){
7151       // c = bit & literal;
7152       if(lit>>1){
7153         // lit>>1  != 0 => result = 1
7154         if(AOP_TYPE(result) == AOP_CRY){
7155           if(size)
7156             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
7157             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7158           else if(ifx)
7159             continueIfTrue(ifx);
7160           goto release;
7161         }
7162         pic16_emitcode("setb","c");
7163       } else{
7164         // lit == (0 or 1)
7165         if(lit == 0){
7166           // lit == 0, result = left
7167           if(size && pic16_sameRegs(AOP(result),AOP(left)))
7168             goto release;
7169           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7170         } else{
7171           // lit == 1, result = not(left)
7172           if(size && pic16_sameRegs(AOP(result),AOP(left))){
7173             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
7174             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
7175             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7176             goto release;
7177           } else {
7178             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7179             pic16_emitcode("cpl","c");
7180           }
7181         }
7182       }
7183
7184     } else {
7185       // right != literal
7186       symbol *tlbl = newiTempLabel(NULL);
7187       if (AOP_TYPE(right) == AOP_CRY){
7188         // c = bit ^ bit;
7189         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7190       }
7191       else{
7192         int sizer = AOP_SIZE(right);
7193         // c = bit ^ val
7194         // if val>>1 != 0, result = 1
7195         pic16_emitcode("setb","c");
7196         while(sizer){
7197           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
7198           if(sizer == 1)
7199             // test the msb of the lsb
7200             pic16_emitcode("anl","a,#0xfe");
7201           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7202           sizer--;
7203         }
7204         // val = (0,1)
7205         pic16_emitcode("rrc","a");
7206       }
7207       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
7208       pic16_emitcode("cpl","c");
7209       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
7210     }
7211     // bit = c
7212     // val = c
7213     if(size)
7214       pic16_outBitC(result);
7215     // if(bit | ...)
7216     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7217       genIfxJump(ifx, "c");           
7218     goto release ;
7219   }
7220
7221   if(pic16_sameRegs(AOP(result),AOP(left))){
7222     /* if left is same as result */
7223     for(;size--; offset++) {
7224       if(AOP_TYPE(right) == AOP_LIT){
7225         int t  = (lit >> (offset*8)) & 0x0FFL;
7226         if(t == 0x00L)
7227           continue;
7228         else
7229           if (IS_AOP_PREG(left)) {
7230             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7231             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7232             pic16_aopPut(AOP(result),"a",offset);
7233           } else {
7234             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7235             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7236             pic16_emitcode("xrl","%s,%s",
7237                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7238                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7239           }
7240       } else {
7241         if (AOP_TYPE(left) == AOP_ACC)
7242           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7243         else {
7244           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7245           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7246 /*
7247           if (IS_AOP_PREG(left)) {
7248             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7249             pic16_aopPut(AOP(result),"a",offset);
7250           } else
7251             pic16_emitcode("xrl","%s,a",
7252                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7253 */
7254         }
7255       }
7256     }
7257   } else {
7258     // left & result in different registers
7259     if(AOP_TYPE(result) == AOP_CRY){
7260       // result = bit
7261       // if(size), result in bit
7262       // if(!size && ifx), conditional oper: if(left ^ right)
7263       symbol *tlbl = newiTempLabel(NULL);
7264       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7265       if(size)
7266         pic16_emitcode("setb","c");
7267       while(sizer--){
7268         if((AOP_TYPE(right) == AOP_LIT) &&
7269            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7270           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7271         } else {
7272           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7273           pic16_emitcode("xrl","a,%s",
7274                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7275         }
7276         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7277         offset++;
7278       }
7279       if(size){
7280         CLRC;
7281         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7282         pic16_outBitC(result);
7283       } else if(ifx)
7284         jmpTrueOrFalse(ifx, tlbl);
7285     } else for(;(size--);offset++){
7286       // normal case
7287       // result = left & right
7288       if(AOP_TYPE(right) == AOP_LIT){
7289         int t = (lit >> (offset*8)) & 0x0FFL;
7290         switch(t) { 
7291         case 0x00:
7292           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7293           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7294           pic16_emitcode("movf","%s,w",
7295                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7296           pic16_emitcode("movwf","%s",
7297                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7298           break;
7299         case 0xff:
7300           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7301           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7302           pic16_emitcode("comf","%s,w",
7303                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7304           pic16_emitcode("movwf","%s",
7305                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7306           break;
7307         default:
7308           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7309           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7310           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7311           pic16_emitcode("movlw","0x%x",t);
7312           pic16_emitcode("xorwf","%s,w",
7313                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7314           pic16_emitcode("movwf","%s",
7315                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7316
7317         }
7318         continue;
7319       }
7320
7321       // faster than result <- left, anl result,right
7322       // and better if result is SFR
7323       if (AOP_TYPE(left) == AOP_ACC) {
7324         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7325         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7326       } else {
7327         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7328         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7329         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7330         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7331       }
7332       if ( AOP_TYPE(result) != AOP_ACC){
7333         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7334         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7335       }
7336     }
7337   }
7338
7339   release :
7340     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7341   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7342   pic16_freeAsmop(result,NULL,ic,TRUE);     
7343 }
7344
7345 /*-----------------------------------------------------------------*/
7346 /* genInline - write the inline code out                           */
7347 /*-----------------------------------------------------------------*/
7348 static void genInline (iCode *ic)
7349 {
7350   char *buffer, *bp, *bp1;
7351     
7352         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7353
7354         _G.inLine += (!options.asmpeep);
7355
7356         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7357         strcpy(buffer,IC_INLINE(ic));
7358
7359 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7360
7361         /* emit each line as a code */
7362         while (*bp) {
7363                 if (*bp == '\n') {
7364                         *bp++ = '\0';
7365
7366                         if(*bp1)
7367                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7368                         bp1 = bp;
7369                 } else {
7370                         if (*bp == ':') {
7371                                 bp++;
7372                                 *bp = '\0';
7373                                 bp++;
7374
7375                                 /* print label, use this special format with NULL directive
7376                                  * to denote that the argument should not be indented with tab */
7377                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7378                                 bp1 = bp;
7379                         } else
7380                                 bp++;
7381                 }
7382         }
7383
7384         if ((bp1 != bp) && *bp1)
7385                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7386
7387
7388     Safe_free(buffer);
7389
7390     _G.inLine -= (!options.asmpeep);
7391 }
7392
7393 /*-----------------------------------------------------------------*/
7394 /* genRRC - rotate right with carry                                */
7395 /*-----------------------------------------------------------------*/
7396 static void genRRC (iCode *ic)
7397 {
7398   operand *left , *result ;
7399   int size, offset = 0, same;
7400
7401   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7402
7403   /* rotate right with carry */
7404   left = IC_LEFT(ic);
7405   result=IC_RESULT(ic);
7406   pic16_aopOp (left,ic,FALSE);
7407   pic16_aopOp (result,ic,FALSE);
7408
7409   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7410
7411   same = pic16_sameRegs(AOP(result),AOP(left));
7412
7413   size = AOP_SIZE(result);    
7414
7415   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7416
7417   /* get the lsb and put it into the carry */
7418   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7419
7420   offset = 0 ;
7421
7422   while(size--) {
7423
7424     if(same) {
7425       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7426     } else {
7427       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7428       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7429     }
7430
7431     offset++;
7432   }
7433
7434   pic16_freeAsmop(left,NULL,ic,TRUE);
7435   pic16_freeAsmop(result,NULL,ic,TRUE);
7436 }
7437
7438 /*-----------------------------------------------------------------*/
7439 /* genRLC - generate code for rotate left with carry               */
7440 /*-----------------------------------------------------------------*/
7441 static void genRLC (iCode *ic)
7442 {    
7443   operand *left , *result ;
7444   int size, offset = 0;
7445   int same;
7446
7447   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7448   /* rotate right with carry */
7449   left = IC_LEFT(ic);
7450   result=IC_RESULT(ic);
7451   pic16_aopOp (left,ic,FALSE);
7452   pic16_aopOp (result,ic,FALSE);
7453
7454   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7455
7456   same = pic16_sameRegs(AOP(result),AOP(left));
7457
7458   /* move it to the result */
7459   size = AOP_SIZE(result);    
7460
7461   /* get the msb and put it into the carry */
7462   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7463
7464   offset = 0 ;
7465
7466   while(size--) {
7467
7468     if(same) {
7469       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7470     } else {
7471       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7472       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7473     }
7474
7475     offset++;
7476   }
7477
7478
7479   pic16_freeAsmop(left,NULL,ic,TRUE);
7480   pic16_freeAsmop(result,NULL,ic,TRUE);
7481 }
7482
7483
7484 /* gpasm can get the highest order bit with HIGH/UPPER
7485  * so the following probably is not needed -- VR */
7486  
7487 /*-----------------------------------------------------------------*/
7488 /* genGetHbit - generates code get highest order bit               */
7489 /*-----------------------------------------------------------------*/
7490 static void genGetHbit (iCode *ic)
7491 {
7492     operand *left, *result;
7493     left = IC_LEFT(ic);
7494     result=IC_RESULT(ic);
7495     pic16_aopOp (left,ic,FALSE);
7496     pic16_aopOp (result,ic,FALSE);
7497
7498     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7499     /* get the highest order byte into a */
7500     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7501     if(AOP_TYPE(result) == AOP_CRY){
7502         pic16_emitcode("rlc","a");
7503         pic16_outBitC(result);
7504     }
7505     else{
7506         pic16_emitcode("rl","a");
7507         pic16_emitcode("anl","a,#0x01");
7508         pic16_outAcc(result);
7509     }
7510
7511
7512     pic16_freeAsmop(left,NULL,ic,TRUE);
7513     pic16_freeAsmop(result,NULL,ic,TRUE);
7514 }
7515
7516 #if 0
7517 /*-----------------------------------------------------------------*/
7518 /* AccRol - rotate left accumulator by known count                 */
7519 /*-----------------------------------------------------------------*/
7520 static void AccRol (int shCount)
7521 {
7522     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7523     shCount &= 0x0007;              // shCount : 0..7
7524     switch(shCount){
7525         case 0 :
7526             break;
7527         case 1 :
7528             pic16_emitcode("rl","a");
7529             break;
7530         case 2 :
7531             pic16_emitcode("rl","a");
7532             pic16_emitcode("rl","a");
7533             break;
7534         case 3 :
7535             pic16_emitcode("swap","a");
7536             pic16_emitcode("rr","a");
7537             break;
7538         case 4 :
7539             pic16_emitcode("swap","a");
7540             break;
7541         case 5 :
7542             pic16_emitcode("swap","a");
7543             pic16_emitcode("rl","a");
7544             break;
7545         case 6 :
7546             pic16_emitcode("rr","a");
7547             pic16_emitcode("rr","a");
7548             break;
7549         case 7 :
7550             pic16_emitcode("rr","a");
7551             break;
7552     }
7553 }
7554 #endif
7555
7556 /*-----------------------------------------------------------------*/
7557 /* AccLsh - left shift accumulator by known count                  */
7558 /*-----------------------------------------------------------------*/
7559 static void AccLsh (int shCount)
7560 {
7561         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7562         switch(shCount){
7563                 case 0 :
7564                         return;
7565                         break;
7566                 case 1 :
7567                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7568                         break;
7569                 case 2 :
7570                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7571                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7572                         break;
7573                 case 3 :
7574                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7575                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7576                         break;
7577                 case 4 :
7578                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7579                         break;
7580                 case 5 :
7581                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7582                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7583                         break;
7584                 case 6 :
7585                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7586                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7587                         break;
7588                 case 7 :
7589                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7590                         break;
7591         }
7592
7593         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7594 }
7595
7596 /*-----------------------------------------------------------------*/
7597 /* AccRsh - right shift accumulator by known count                 */
7598 /*-----------------------------------------------------------------*/
7599 static void AccRsh (int shCount, int andmask)
7600 {
7601         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7602         switch(shCount){
7603                 case 0 :
7604                         return; break;
7605                 case 1 :
7606                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7607 //                      andmask = 0;    /* no need */
7608                         break;
7609                 case 2 :
7610                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7611                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7612 //                      andmask = 0;    /* no need */
7613                         break;
7614                 case 3 :
7615                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7616                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7617                         break;
7618                 case 4 :
7619                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7620                         break;
7621                 case 5 :
7622                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7623                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7624                         break;
7625                 case 6 :
7626                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7627                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7628                         break;
7629                 case 7 :
7630                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7631                         break;
7632         }
7633         
7634         if(andmask)
7635                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7636         else
7637                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7638 }
7639
7640 #if 0
7641 /*-----------------------------------------------------------------*/
7642 /* AccSRsh - signed right shift accumulator by known count                 */
7643 /*-----------------------------------------------------------------*/
7644 static void AccSRsh (int shCount)
7645 {
7646     symbol *tlbl ;
7647     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7648     if(shCount != 0){
7649         if(shCount == 1){
7650             pic16_emitcode("mov","c,acc.7");
7651             pic16_emitcode("rrc","a");
7652         } else if(shCount == 2){
7653             pic16_emitcode("mov","c,acc.7");
7654             pic16_emitcode("rrc","a");
7655             pic16_emitcode("mov","c,acc.7");
7656             pic16_emitcode("rrc","a");
7657         } else {
7658             tlbl = newiTempLabel(NULL);
7659             /* rotate right accumulator */
7660             AccRol(8 - shCount);
7661             /* and kill the higher order bits */
7662             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7663             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7664             pic16_emitcode("orl","a,#0x%02x",
7665                      (unsigned char)~SRMask[shCount]);
7666             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7667         }
7668     }
7669 }
7670 #endif
7671 /*-----------------------------------------------------------------*/
7672 /* shiftR1Left2Result - shift right one byte from left to result   */
7673 /*-----------------------------------------------------------------*/
7674 static void shiftR1Left2ResultSigned (operand *left, int offl,
7675                                 operand *result, int offr,
7676                                 int shCount)
7677 {
7678   int same;
7679
7680   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7681
7682   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7683
7684   switch(shCount) {
7685   case 1:
7686     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7687     if(same) 
7688       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7689     else {
7690       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7691       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7692     }
7693
7694     break;
7695   case 2:
7696
7697     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7698     if(same) 
7699       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7700     else {
7701       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7702       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7703     }
7704     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7705     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7706
7707     break;
7708
7709   case 3:
7710     if(same)
7711       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7712     else {
7713       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7714       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7715     }
7716
7717     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7718     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7719     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7720
7721     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7722     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7723
7724     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7725     break;
7726
7727   case 4:
7728     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7729     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
7730     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7731     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
7732     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7733     break;
7734   case 5:
7735     if(same) {
7736       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
7737     } else {
7738       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
7739       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7740     }
7741     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
7742     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
7743     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7744     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
7745     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7746     break;
7747
7748   case 6:
7749     if(same) {
7750       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7751       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7752       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7753       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7754       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7755       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7756     } else {
7757       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7758       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7759       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7760       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7761       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7762     }
7763     break;
7764
7765   case 7:
7766     if(same) {
7767       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7768       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7769       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7770       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7771     } else {
7772       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7773       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7774       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7775     }
7776
7777   default:
7778     break;
7779   }
7780 }
7781
7782 /*-----------------------------------------------------------------*/
7783 /* shiftR1Left2Result - shift right one byte from left to result   */
7784 /*-----------------------------------------------------------------*/
7785 static void shiftR1Left2Result (operand *left, int offl,
7786                                 operand *result, int offr,
7787                                 int shCount, int sign)
7788 {
7789   int same;
7790
7791   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7792
7793   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7794
7795   /* Copy the msb into the carry if signed. */
7796   if(sign) {
7797     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7798     return;
7799   }
7800
7801
7802
7803   switch(shCount) {
7804   case 1:
7805     emitCLRC;
7806     if(same) 
7807       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7808     else {
7809       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7810       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7811     }
7812     break;
7813   case 2:
7814     emitCLRC;
7815     if(same) {
7816       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7817     } else {
7818       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7819       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7820     }
7821     emitCLRC;
7822     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7823
7824     break;
7825   case 3:
7826     if(same)
7827       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7828     else {
7829       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7830       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7831     }
7832
7833     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7834     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7835     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7836     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7837     break;
7838       
7839   case 4:
7840     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7841     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7842     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7843     break;
7844
7845   case 5:
7846     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7847     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7848     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7849     emitCLRC;
7850     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7851
7852     break;
7853   case 6:
7854
7855     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
7856     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7857     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7858     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7859     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7860     break;
7861
7862   case 7:
7863
7864     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7865     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7866     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7867
7868     break;
7869
7870   default:
7871     break;
7872   }
7873 }
7874
7875 /*-----------------------------------------------------------------*/
7876 /* shiftL1Left2Result - shift left one byte from left to result    */
7877 /*-----------------------------------------------------------------*/
7878 static void shiftL1Left2Result (operand *left, int offl,
7879                                 operand *result, int offr, int shCount)
7880 {
7881   int same;
7882
7883   //    char *l;
7884   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7885
7886   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7887   DEBUGpic16_emitcode ("; ***","same =  %d",same);
7888     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7889     //    MOVA(l);
7890     /* shift left accumulator */
7891     //AccLsh(shCount); // don't comment out just yet...
7892   //    pic16_aopPut(AOP(result),"a",offr);
7893
7894   switch(shCount) {
7895   case 1:
7896     /* Shift left 1 bit position */
7897     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7898     if(same) {
7899       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7900     } else {
7901       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7902       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7903     }
7904     break;
7905   case 2:
7906     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7907     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7908     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7909     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7910     break;
7911   case 3:
7912     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7913     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7914     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7915     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7916     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7917     break;
7918   case 4:
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     break;
7923   case 5:
7924     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7925     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7926     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7927     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7928     break;
7929   case 6:
7930     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7931     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7932     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7933     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7934     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7935     break;
7936   case 7:
7937     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7938     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7939     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7940     break;
7941
7942   default:
7943     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7944   }
7945
7946 }
7947
7948 /*-----------------------------------------------------------------*/
7949 /* movLeft2Result - move byte from left to result                  */
7950 /*-----------------------------------------------------------------*/
7951 static void movLeft2Result (operand *left, int offl,
7952                             operand *result, int offr)
7953 {
7954   char *l;
7955   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7956   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7957     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7958
7959     if (*l == '@' && (IS_AOP_PREG(result))) {
7960       pic16_emitcode("mov","a,%s",l);
7961       pic16_aopPut(AOP(result),"a",offr);
7962     } else {
7963       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7964       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7965     }
7966   }
7967 }
7968
7969 /*-----------------------------------------------------------------*/
7970 /* shiftL2Left2Result - shift left two bytes from left to result   */
7971 /*-----------------------------------------------------------------*/
7972 static void shiftL2Left2Result (operand *left, int offl,
7973                                 operand *result, int offr, int shCount)
7974 {
7975   int same = pic16_sameRegs(AOP(result), AOP(left));
7976   int i;
7977
7978   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7979
7980   if (same && (offl != offr)) { // shift bytes
7981     if (offr > offl) {
7982        for(i=1;i>-1;i--) {
7983          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7984          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7985        }
7986     } else { // just treat as different later on
7987                 same = 0;
7988     }
7989   }
7990
7991   if(same) {
7992     switch(shCount) {
7993     case 0:
7994       break;
7995     case 1:
7996     case 2:
7997     case 3:
7998
7999       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8000       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8001       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8002
8003       while(--shCount) {
8004                 emitCLRC;
8005                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8006                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8007       }
8008
8009       break;
8010     case 4:
8011     case 5:
8012       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8013       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8014       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8015       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8016       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8017       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8018       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8019       if(shCount >=5) {
8020                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8021                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8022       }
8023       break;
8024     case 6:
8025       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8026       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8027       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8028       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8029       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8030       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8031       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8032       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8033       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8034       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8035       break;
8036     case 7:
8037       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8038       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8039       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8040       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8041       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8042     }
8043
8044   } else {
8045     switch(shCount) {
8046     case 0:
8047       break;
8048     case 1:
8049     case 2:
8050     case 3:
8051       /* note, use a mov/add for the shift since the mov has a
8052          chance of getting optimized out */
8053       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8054       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8055       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8056       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8057       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8058
8059       while(--shCount) {
8060                 emitCLRC;
8061                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8062                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8063       }
8064       break;
8065
8066     case 4:
8067     case 5:
8068       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8069       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8070       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8071       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8072       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8073       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8074       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8075       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8076
8077
8078       if(shCount == 5) {
8079                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8080                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8081       }
8082       break;
8083     case 6:
8084       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8085       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8086       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8087       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8088
8089       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8090       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8091       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8092       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8093       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8094       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8095       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8096       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8097       break;
8098     case 7:
8099       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8100       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8101       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8102       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8103       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8104     }
8105   }
8106
8107 }
8108 /*-----------------------------------------------------------------*/
8109 /* shiftR2Left2Result - shift right two bytes from left to result  */
8110 /*-----------------------------------------------------------------*/
8111 static void shiftR2Left2Result (operand *left, int offl,
8112                                 operand *result, int offr,
8113                                 int shCount, int sign)
8114 {
8115   int same = pic16_sameRegs(AOP(result), AOP(left));
8116   int i;
8117   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8118
8119   if (same && (offl != offr)) { // shift right bytes
8120     if (offr < offl) {
8121        for(i=0;i<2;i++) {
8122          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8123          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8124        }
8125     } else { // just treat as different later on
8126                 same = 0;
8127     }
8128   }
8129
8130   switch(shCount) {
8131   case 0:
8132     break;
8133   case 1:
8134   case 2:
8135   case 3:
8136     if(sign)
8137       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8138     else
8139       emitCLRC;
8140
8141     if(same) {
8142       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8143       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8144     } else {
8145       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8146       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8147       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8148       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8149     }
8150
8151     while(--shCount) {
8152       if(sign)
8153                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8154       else
8155                 emitCLRC;
8156       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8157       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8158     }
8159     break;
8160   case 4:
8161   case 5:
8162     if(same) {
8163
8164       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
8165       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
8166       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8167
8168       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8169       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
8170       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8171       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8172     } else {
8173       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8174       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8175       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8176
8177       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8178       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8179       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8180       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8181       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8182     }
8183
8184     if(shCount >=5) {
8185       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8186       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8187     }
8188
8189     if(sign) {
8190       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
8191       pic16_emitpcode(POC_BTFSC, 
8192                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
8193       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8194     }
8195
8196     break;
8197
8198   case 6:
8199     if(same) {
8200
8201       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8202       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8203
8204       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8205       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8206       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8207       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8208       if(sign) {
8209         pic16_emitpcode(POC_BTFSC, 
8210                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8211         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8212       }
8213       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8214       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
8215       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8216       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8217     } else {
8218       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8219       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8220       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8221       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8222       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8223       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8224       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8225       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8226       if(sign) {
8227         pic16_emitpcode(POC_BTFSC, 
8228                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8229         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8230       }
8231       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8232       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8233
8234         
8235     }
8236
8237     break;
8238   case 7:
8239     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8240     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8241     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8242     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8243     if(sign) {
8244       emitSKPNC;
8245       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8246     } else 
8247       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8248   }
8249 }
8250
8251
8252 /*-----------------------------------------------------------------*/
8253 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8254 /*-----------------------------------------------------------------*/
8255 static void shiftLLeftOrResult (operand *left, int offl,
8256                                 operand *result, int offr, int shCount)
8257 {
8258     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8259
8260     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8261     /* shift left accumulator */
8262     AccLsh(shCount);
8263     /* or with result */
8264     /* back to result */
8265     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8266 }
8267
8268 /*-----------------------------------------------------------------*/
8269 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8270 /*-----------------------------------------------------------------*/
8271 static void shiftRLeftOrResult (operand *left, int offl,
8272                                 operand *result, int offr, int shCount)
8273 {
8274     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8275     
8276     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8277     /* shift right accumulator */
8278     AccRsh(shCount, 1);
8279     /* or with result */
8280     /* back to result */
8281     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8282 }
8283
8284 /*-----------------------------------------------------------------*/
8285 /* genlshOne - left shift a one byte quantity by known count       */
8286 /*-----------------------------------------------------------------*/
8287 static void genlshOne (operand *result, operand *left, int shCount)
8288 {       
8289     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8290     shiftL1Left2Result(left, LSB, result, LSB, shCount);
8291 }
8292
8293 /*-----------------------------------------------------------------*/
8294 /* genlshTwo - left shift two bytes by known amount != 0           */
8295 /*-----------------------------------------------------------------*/
8296 static void genlshTwo (operand *result,operand *left, int shCount)
8297 {
8298     int size;
8299     
8300     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8301     size = pic16_getDataSize(result);
8302
8303     /* if shCount >= 8 */
8304     if (shCount >= 8) {
8305         shCount -= 8 ;
8306
8307         if (size > 1){
8308             if (shCount)
8309                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8310             else 
8311                 movLeft2Result(left, LSB, result, MSB16);
8312         }
8313         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8314     }
8315
8316     /*  1 <= shCount <= 7 */
8317     else {  
8318         if(size == 1)
8319             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
8320         else 
8321             shiftL2Left2Result(left, LSB, result, LSB, shCount);
8322     }
8323 }
8324
8325 /*-----------------------------------------------------------------*/
8326 /* shiftLLong - shift left one long from left to result            */
8327 /* offr = LSB or MSB16                                             */
8328 /*-----------------------------------------------------------------*/
8329 static void shiftLLong (operand *left, operand *result, int offr )
8330 {
8331     int size = AOP_SIZE(result);
8332     int same = pic16_sameRegs(AOP(left),AOP(result));
8333         int i;
8334
8335     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8336
8337         if (same && (offr == MSB16)) { //shift one byte
8338                 for(i=size-1;i>=MSB16;i--) {
8339                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8340                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8341                 }
8342         } else {
8343                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8344         }
8345         
8346     if (size >= LSB+offr ){
8347                 if (same) {
8348                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8349                 } else {
8350                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8351                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8352                 }
8353          }
8354
8355     if(size >= MSB16+offr){
8356                 if (same) {
8357                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8358                 } else {
8359                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8360                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8361                 }
8362     }
8363
8364     if(size >= MSB24+offr){
8365                 if (same) {
8366                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8367                 } else {
8368                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8369                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8370                 }
8371     }
8372
8373     if(size > MSB32+offr){
8374                 if (same) {
8375                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8376                 } else {
8377                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8378                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8379                 }
8380     }
8381     if(offr != LSB)
8382                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8383
8384 }
8385
8386 /*-----------------------------------------------------------------*/
8387 /* genlshFour - shift four byte by a known amount != 0             */
8388 /*-----------------------------------------------------------------*/
8389 static void genlshFour (operand *result, operand *left, int shCount)
8390 {
8391     int size;
8392
8393     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8394     size = AOP_SIZE(result);
8395
8396     /* if shifting more that 3 bytes */
8397     if (shCount >= 24 ) {
8398         shCount -= 24;
8399         if (shCount)
8400             /* lowest order of left goes to the highest
8401             order of the destination */
8402             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8403         else
8404             movLeft2Result(left, LSB, result, MSB32);
8405
8406                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8407                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8408                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8409
8410         return;
8411     }
8412
8413     /* more than two bytes */
8414     else if ( shCount >= 16 ) {
8415         /* lower order two bytes goes to higher order two bytes */
8416         shCount -= 16;
8417         /* if some more remaining */
8418         if (shCount)
8419             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8420         else {
8421             movLeft2Result(left, MSB16, result, MSB32);
8422             movLeft2Result(left, LSB, result, MSB24);
8423         }
8424                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8425                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8426         return;
8427     }    
8428
8429     /* if more than 1 byte */
8430     else if ( shCount >= 8 ) {
8431         /* lower order three bytes goes to higher order  three bytes */
8432         shCount -= 8;
8433         if(size == 2){
8434             if(shCount)
8435                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8436             else
8437                 movLeft2Result(left, LSB, result, MSB16);
8438         }
8439         else{   /* size = 4 */
8440             if(shCount == 0){
8441                 movLeft2Result(left, MSB24, result, MSB32);
8442                 movLeft2Result(left, MSB16, result, MSB24);
8443                 movLeft2Result(left, LSB, result, MSB16);
8444                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8445             }
8446             else if(shCount == 1)
8447                 shiftLLong(left, result, MSB16);
8448             else{
8449                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8450                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8451                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8452                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8453             }
8454         }
8455     }
8456
8457     /* 1 <= shCount <= 7 */
8458     else if(shCount <= 3)
8459     { 
8460         shiftLLong(left, result, LSB);
8461         while(--shCount >= 1)
8462             shiftLLong(result, result, LSB);
8463     }
8464     /* 3 <= shCount <= 7, optimize */
8465     else{
8466         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8467         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8468         shiftL2Left2Result(left, LSB, result, LSB, shCount);
8469     }
8470 }
8471
8472 /*-----------------------------------------------------------------*/
8473 /* genLeftShiftLiteral - left shifting by known count              */
8474 /*-----------------------------------------------------------------*/
8475 static void genLeftShiftLiteral (operand *left,
8476                                  operand *right,
8477                                  operand *result,
8478                                  iCode *ic)
8479 {    
8480     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8481     int size;
8482
8483     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8484     pic16_freeAsmop(right,NULL,ic,TRUE);
8485
8486     pic16_aopOp(left,ic,FALSE);
8487     pic16_aopOp(result,ic,FALSE);
8488
8489     size = getSize(operandType(result));
8490
8491 #if VIEW_SIZE
8492     pic16_emitcode("; shift left ","result %d, left %d",size,
8493              AOP_SIZE(left));
8494 #endif
8495
8496     /* I suppose that the left size >= result size */
8497     if(shCount == 0){
8498         while(size--){
8499             movLeft2Result(left, size, result, size);
8500         }
8501     }
8502
8503     else if(shCount >= (size * 8))
8504         while(size--)
8505             pic16_aopPut(AOP(result),zero,size);
8506     else{
8507         switch (size) {
8508             case 1:
8509                 genlshOne (result,left,shCount);
8510                 break;
8511
8512             case 2:
8513             case 3:
8514                 genlshTwo (result,left,shCount);
8515                 break;
8516
8517             case 4:
8518                 genlshFour (result,left,shCount);
8519                 break;
8520         }
8521     }
8522     pic16_freeAsmop(left,NULL,ic,TRUE);
8523     pic16_freeAsmop(result,NULL,ic,TRUE);
8524 }
8525
8526 /*-----------------------------------------------------------------*
8527  * genMultiAsm - repeat assembly instruction for size of register.
8528  * if endian == 1, then the high byte (i.e base address + size of 
8529  * register) is used first else the low byte is used first;
8530  *-----------------------------------------------------------------*/
8531 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8532 {
8533
8534   int offset = 0;
8535
8536   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8537
8538   if(!reg)
8539     return;
8540
8541   if(!endian) {
8542     endian = 1;
8543   } else {
8544     endian = -1;
8545     offset = size-1;
8546   }
8547
8548   while(size--) {
8549     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
8550     offset += endian;
8551   }
8552
8553 }
8554 /*-----------------------------------------------------------------*/
8555 /* genLeftShift - generates code for left shifting                 */
8556 /*-----------------------------------------------------------------*/
8557 static void genLeftShift (iCode *ic)
8558 {
8559   operand *left,*right, *result;
8560   int size, offset;
8561   char *l;
8562   symbol *tlbl , *tlbl1;
8563   pCodeOp *pctemp;
8564
8565   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8566
8567   right = IC_RIGHT(ic);
8568   left  = IC_LEFT(ic);
8569   result = IC_RESULT(ic);
8570
8571   pic16_aopOp(right,ic,FALSE);
8572
8573   /* if the shift count is known then do it 
8574      as efficiently as possible */
8575   if (AOP_TYPE(right) == AOP_LIT) {
8576     genLeftShiftLiteral (left,right,result,ic);
8577     return ;
8578   }
8579
8580   /* shift count is unknown then we have to form 
8581      a loop get the loop count in B : Note: we take
8582      only the lower order byte since shifting
8583      more that 32 bits make no sense anyway, ( the
8584      largest size of an object can be only 32 bits ) */  
8585
8586     
8587   pic16_aopOp(left,ic,FALSE);
8588   pic16_aopOp(result,ic,FALSE);
8589
8590   /* now move the left to the result if they are not the
8591      same */
8592   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8593       AOP_SIZE(result) > 1) {
8594
8595     size = AOP_SIZE(result);
8596     offset=0;
8597     while (size--) {
8598       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8599       if (*l == '@' && (IS_AOP_PREG(result))) {
8600
8601         pic16_emitcode("mov","a,%s",l);
8602         pic16_aopPut(AOP(result),"a",offset);
8603       } else {
8604         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8605         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8606         //pic16_aopPut(AOP(result),l,offset);
8607       }
8608       offset++;
8609     }
8610   }
8611
8612   size = AOP_SIZE(result);
8613
8614   /* if it is only one byte then */
8615   if (size == 1) {
8616     if(optimized_for_speed) {
8617       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8618       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
8619       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
8620       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8621       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8622       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8623       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8624       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
8625       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
8626       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
8627       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8628       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8629     } else {
8630
8631       tlbl = newiTempLabel(NULL);
8632       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8633                 pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8634                 pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8635       }
8636
8637       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8638       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8639       pic16_emitpLabel(tlbl->key);
8640       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8641       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8642       emitSKPC;
8643       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8644     }
8645     goto release ;
8646   }
8647     
8648   if (pic16_sameRegs(AOP(left),AOP(result))) {
8649
8650     tlbl = newiTempLabel(NULL);
8651     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8652     genMultiAsm(POC_RRCF, result, size,1);
8653     pic16_emitpLabel(tlbl->key);
8654     genMultiAsm(POC_RLCF, result, size,0);
8655     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8656     emitSKPC;
8657     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8658     goto release;
8659   }
8660
8661   //tlbl = newiTempLabel(NULL);
8662   //offset = 0 ;   
8663   //tlbl1 = newiTempLabel(NULL);
8664
8665   //reAdjustPreg(AOP(result));    
8666     
8667   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
8668   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8669   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8670   //MOVA(l);
8671   //pic16_emitcode("add","a,acc");         
8672   //pic16_aopPut(AOP(result),"a",offset++);
8673   //while (--size) {
8674   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8675   //  MOVA(l);
8676   //  pic16_emitcode("rlc","a");         
8677   //  pic16_aopPut(AOP(result),"a",offset++);
8678   //}
8679   //reAdjustPreg(AOP(result));
8680
8681   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8682   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8683
8684
8685   tlbl = newiTempLabel(NULL);
8686   tlbl1= newiTempLabel(NULL);
8687
8688   size = AOP_SIZE(result);
8689   offset = 1;
8690
8691   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8692
8693   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8694
8695   /* offset should be 0, 1 or 3 */
8696   
8697   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8698   emitSKPNZ;
8699   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8700
8701   pic16_emitpcode(POC_MOVWF, pctemp);
8702
8703
8704   pic16_emitpLabel(tlbl->key);
8705
8706   emitCLRC;
8707   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
8708   while(--size)
8709     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
8710
8711   pic16_emitpcode(POC_DECFSZ,  pctemp);
8712   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8713   pic16_emitpLabel(tlbl1->key);
8714
8715   pic16_popReleaseTempReg(pctemp);
8716
8717
8718  release:
8719   pic16_freeAsmop (right,NULL,ic,TRUE);
8720   pic16_freeAsmop(left,NULL,ic,TRUE);
8721   pic16_freeAsmop(result,NULL,ic,TRUE);
8722 }
8723
8724 /*-----------------------------------------------------------------*/
8725 /* genrshOne - right shift a one byte quantity by known count      */
8726 /*-----------------------------------------------------------------*/
8727 static void genrshOne (operand *result, operand *left,
8728                        int shCount, int sign)
8729 {
8730     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8731     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8732 }
8733
8734 /*-----------------------------------------------------------------*/
8735 /* genrshTwo - right shift two bytes by known amount != 0          */
8736 /*-----------------------------------------------------------------*/
8737 static void genrshTwo (operand *result,operand *left,
8738                        int shCount, int sign)
8739 {
8740   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8741   /* if shCount >= 8 */
8742   if (shCount >= 8) {
8743     shCount -= 8 ;
8744     if (shCount)
8745       shiftR1Left2Result(left, MSB16, result, LSB,
8746                          shCount, sign);
8747     else
8748       movLeft2Result(left, MSB16, result, LSB);
8749
8750     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8751
8752     if(sign) {
8753       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8754       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8755     }
8756   }
8757
8758   /*  1 <= shCount <= 7 */
8759   else
8760     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
8761 }
8762
8763 /*-----------------------------------------------------------------*/
8764 /* shiftRLong - shift right one long from left to result           */
8765 /* offl = LSB or MSB16                                             */
8766 /*-----------------------------------------------------------------*/
8767 static void shiftRLong (operand *left, int offl,
8768                         operand *result, int sign)
8769 {
8770     int size = AOP_SIZE(result);
8771     int same = pic16_sameRegs(AOP(left),AOP(result));
8772     int i;
8773     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8774
8775         if (same && (offl == MSB16)) { //shift one byte right
8776                 for(i=MSB16;i<size;i++) {
8777                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8778                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8779                 }
8780         }
8781
8782     if(sign)
8783                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8784         else
8785                 emitCLRC;
8786
8787         if (same) {
8788                 if (offl == LSB)
8789                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8790         } else {
8791         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8792         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8793         }
8794
8795     if(offl == MSB16) {
8796         /* add sign of "a" */
8797         pic16_addSign(result, MSB32, sign);
8798         }
8799
8800         if (same) {
8801         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8802         } else {
8803         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8804         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8805         }
8806         
8807         if (same) {
8808         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8809         } else {
8810         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8811         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8812         }
8813
8814         if (same) {
8815         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8816         } else {
8817         if(offl == LSB){
8818                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8819                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8820         }
8821         }
8822 }
8823
8824 /*-----------------------------------------------------------------*/
8825 /* genrshFour - shift four byte by a known amount != 0             */
8826 /*-----------------------------------------------------------------*/
8827 static void genrshFour (operand *result, operand *left,
8828                         int shCount, int sign)
8829 {
8830   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8831   /* if shifting more that 3 bytes */
8832   if(shCount >= 24 ) {
8833     shCount -= 24;
8834     if(shCount)
8835       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8836     else
8837       movLeft2Result(left, MSB32, result, LSB);
8838
8839     pic16_addSign(result, MSB16, sign);
8840   }
8841   else if(shCount >= 16){
8842     shCount -= 16;
8843     if(shCount)
8844       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8845     else{
8846       movLeft2Result(left, MSB24, result, LSB);
8847       movLeft2Result(left, MSB32, result, MSB16);
8848     }
8849     pic16_addSign(result, MSB24, sign);
8850   }
8851   else if(shCount >= 8){
8852     shCount -= 8;
8853     if(shCount == 1)
8854       shiftRLong(left, MSB16, result, sign);
8855     else if(shCount == 0){
8856       movLeft2Result(left, MSB16, result, LSB);
8857       movLeft2Result(left, MSB24, result, MSB16);
8858       movLeft2Result(left, MSB32, result, MSB24);
8859       pic16_addSign(result, MSB32, sign);
8860     }
8861     else{ //shcount >= 2
8862       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8863       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8864       /* the last shift is signed */
8865       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8866       pic16_addSign(result, MSB32, sign);
8867     }
8868   }
8869   else{   /* 1 <= shCount <= 7 */
8870     if(shCount <= 2){
8871       shiftRLong(left, LSB, result, sign);
8872       if(shCount == 2)
8873         shiftRLong(result, LSB, result, sign);
8874     }
8875     else{
8876       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8877       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8878       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8879     }
8880   }
8881 }
8882
8883 /*-----------------------------------------------------------------*/
8884 /* genRightShiftLiteral - right shifting by known count            */
8885 /*-----------------------------------------------------------------*/
8886 static void genRightShiftLiteral (operand *left,
8887                                   operand *right,
8888                                   operand *result,
8889                                   iCode *ic,
8890                                   int sign)
8891 {    
8892   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8893   int lsize,res_size;
8894
8895   pic16_freeAsmop(right,NULL,ic,TRUE);
8896
8897   pic16_aopOp(left,ic,FALSE);
8898   pic16_aopOp(result,ic,FALSE);
8899
8900   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8901
8902 #if VIEW_SIZE
8903   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8904                  AOP_SIZE(left));
8905 #endif
8906
8907   lsize = pic16_getDataSize(left);
8908   res_size = pic16_getDataSize(result);
8909   /* test the LEFT size !!! */
8910
8911   /* I suppose that the left size >= result size */
8912   if(shCount == 0){
8913     while(res_size--)
8914       movLeft2Result(left, lsize, result, res_size);
8915   }
8916
8917   else if(shCount >= (lsize * 8)){
8918
8919     if(res_size == 1) {
8920       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8921       if(sign) {
8922         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8923         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8924       }
8925     } else {
8926
8927       if(sign) {
8928         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8929         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8930         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8931         while(res_size--)
8932           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8933
8934       } else {
8935
8936         while(res_size--)
8937           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8938       }
8939     }
8940   } else {
8941
8942     switch (res_size) {
8943     case 1:
8944       genrshOne (result,left,shCount,sign);
8945       break;
8946
8947     case 2:
8948       genrshTwo (result,left,shCount,sign);
8949       break;
8950
8951     case 4:
8952       genrshFour (result,left,shCount,sign);
8953       break;
8954     default :
8955       break;
8956     }
8957
8958   }
8959
8960   pic16_freeAsmop(left,NULL,ic,TRUE);
8961   pic16_freeAsmop(result,NULL,ic,TRUE);
8962 }
8963
8964 /*-----------------------------------------------------------------*/
8965 /* genSignedRightShift - right shift of signed number              */
8966 /*-----------------------------------------------------------------*/
8967 static void genSignedRightShift (iCode *ic)
8968 {
8969   operand *right, *left, *result;
8970   int size, offset;
8971   //  char *l;
8972   symbol *tlbl, *tlbl1 ;
8973   pCodeOp *pctemp;
8974
8975   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8976
8977   /* we do it the hard way put the shift count in b
8978      and loop thru preserving the sign */
8979   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8980
8981   right = IC_RIGHT(ic);
8982   left  = IC_LEFT(ic);
8983   result = IC_RESULT(ic);
8984
8985   pic16_aopOp(right,ic,FALSE);  
8986   pic16_aopOp(left,ic,FALSE);
8987   pic16_aopOp(result,ic,FALSE);
8988
8989
8990   if ( AOP_TYPE(right) == AOP_LIT) {
8991     genRightShiftLiteral (left,right,result,ic,1);
8992     return ;
8993   }
8994   /* shift count is unknown then we have to form 
8995      a loop get the loop count in B : Note: we take
8996      only the lower order byte since shifting
8997      more that 32 bits make no sense anyway, ( the
8998      largest size of an object can be only 32 bits ) */  
8999
9000   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9001   //pic16_emitcode("inc","b");
9002   //pic16_freeAsmop (right,NULL,ic,TRUE);
9003   //pic16_aopOp(left,ic,FALSE);
9004   //pic16_aopOp(result,ic,FALSE);
9005
9006   /* now move the left to the result if they are not the
9007      same */
9008   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9009       AOP_SIZE(result) > 1) {
9010
9011     size = AOP_SIZE(result);
9012     offset=0;
9013     while (size--) { 
9014       /*
9015         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9016         if (*l == '@' && IS_AOP_PREG(result)) {
9017
9018         pic16_emitcode("mov","a,%s",l);
9019         pic16_aopPut(AOP(result),"a",offset);
9020         } else
9021         pic16_aopPut(AOP(result),l,offset);
9022       */
9023       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
9024       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
9025
9026       offset++;
9027     }
9028   }
9029
9030   /* mov the highest order bit to OVR */    
9031   tlbl = newiTempLabel(NULL);
9032   tlbl1= newiTempLabel(NULL);
9033
9034   size = AOP_SIZE(result);
9035   offset = size - 1;
9036
9037   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
9038
9039   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9040
9041   /* offset should be 0, 1 or 3 */
9042   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
9043   emitSKPNZ;
9044   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9045
9046   pic16_emitpcode(POC_MOVWF, pctemp);
9047
9048
9049   pic16_emitpLabel(tlbl->key);
9050
9051   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
9052   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
9053
9054   while(--size) {
9055     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
9056   }
9057
9058   pic16_emitpcode(POC_DECFSZ,  pctemp);
9059   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9060   pic16_emitpLabel(tlbl1->key);
9061
9062   pic16_popReleaseTempReg(pctemp);
9063 #if 0
9064   size = AOP_SIZE(result);
9065   offset = size - 1;
9066   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
9067   pic16_emitcode("rlc","a");
9068   pic16_emitcode("mov","ov,c");
9069   /* if it is only one byte then */
9070   if (size == 1) {
9071     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9072     MOVA(l);
9073     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9074     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9075     pic16_emitcode("mov","c,ov");
9076     pic16_emitcode("rrc","a");
9077     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9078     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9079     pic16_aopPut(AOP(result),"a",0);
9080     goto release ;
9081   }
9082
9083   reAdjustPreg(AOP(result));
9084   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9085   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9086   pic16_emitcode("mov","c,ov");
9087   while (size--) {
9088     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9089     MOVA(l);
9090     pic16_emitcode("rrc","a");         
9091     pic16_aopPut(AOP(result),"a",offset--);
9092   }
9093   reAdjustPreg(AOP(result));
9094   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9095   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9096
9097  release:
9098 #endif
9099
9100   pic16_freeAsmop(left,NULL,ic,TRUE);
9101   pic16_freeAsmop(result,NULL,ic,TRUE);
9102   pic16_freeAsmop(right,NULL,ic,TRUE);
9103 }
9104
9105 /*-----------------------------------------------------------------*/
9106 /* genRightShift - generate code for right shifting                */
9107 /*-----------------------------------------------------------------*/
9108 static void genRightShift (iCode *ic)
9109 {
9110     operand *right, *left, *result;
9111     sym_link *letype ;
9112     int size, offset;
9113     char *l;
9114     symbol *tlbl, *tlbl1 ;
9115
9116     /* if signed then we do it the hard way preserve the
9117     sign bit moving it inwards */
9118     letype = getSpec(operandType(IC_LEFT(ic)));
9119     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9120
9121     if (!SPEC_USIGN(letype)) {
9122         genSignedRightShift (ic);
9123         return ;
9124     }
9125
9126     /* signed & unsigned types are treated the same : i.e. the
9127     signed is NOT propagated inwards : quoting from the
9128     ANSI - standard : "for E1 >> E2, is equivalent to division
9129     by 2**E2 if unsigned or if it has a non-negative value,
9130     otherwise the result is implementation defined ", MY definition
9131     is that the sign does not get propagated */
9132
9133     right = IC_RIGHT(ic);
9134     left  = IC_LEFT(ic);
9135     result = IC_RESULT(ic);
9136
9137     pic16_aopOp(right,ic,FALSE);
9138
9139     /* if the shift count is known then do it 
9140     as efficiently as possible */
9141     if (AOP_TYPE(right) == AOP_LIT) {
9142         genRightShiftLiteral (left,right,result,ic, 0);
9143         return ;
9144     }
9145
9146     /* shift count is unknown then we have to form 
9147     a loop get the loop count in B : Note: we take
9148     only the lower order byte since shifting
9149     more that 32 bits make no sense anyway, ( the
9150     largest size of an object can be only 32 bits ) */  
9151
9152     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9153     pic16_emitcode("inc","b");
9154     pic16_aopOp(left,ic,FALSE);
9155     pic16_aopOp(result,ic,FALSE);
9156
9157     /* now move the left to the result if they are not the
9158     same */
9159     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9160         AOP_SIZE(result) > 1) {
9161
9162         size = AOP_SIZE(result);
9163         offset=0;
9164         while (size--) {
9165             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9166             if (*l == '@' && IS_AOP_PREG(result)) {
9167
9168                 pic16_emitcode("mov","a,%s",l);
9169                 pic16_aopPut(AOP(result),"a",offset);
9170             } else
9171                 pic16_aopPut(AOP(result),l,offset);
9172             offset++;
9173         }
9174     }
9175
9176     tlbl = newiTempLabel(NULL);
9177     tlbl1= newiTempLabel(NULL);
9178     size = AOP_SIZE(result);
9179     offset = size - 1;
9180
9181     /* if it is only one byte then */
9182     if (size == 1) {
9183
9184       tlbl = newiTempLabel(NULL);
9185       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9186         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9187         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9188       }
9189
9190       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9191       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9192       pic16_emitpLabel(tlbl->key);
9193       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9194       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9195       emitSKPC;
9196       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9197
9198       goto release ;
9199     }
9200
9201     reAdjustPreg(AOP(result));
9202     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9203     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9204     CLRC;
9205     while (size--) {
9206         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9207         MOVA(l);
9208         pic16_emitcode("rrc","a");         
9209         pic16_aopPut(AOP(result),"a",offset--);
9210     }
9211     reAdjustPreg(AOP(result));
9212
9213     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9214     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9215
9216 release:
9217     pic16_freeAsmop(left,NULL,ic,TRUE);
9218     pic16_freeAsmop (right,NULL,ic,TRUE);
9219     pic16_freeAsmop(result,NULL,ic,TRUE);
9220 }
9221
9222 /*-----------------------------------------------------------------*/
9223 /* genUnpackBits - generates code for unpacking bits               */
9224 /*-----------------------------------------------------------------*/
9225 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
9226 {    
9227     int shCnt ;
9228     int rlen = 0 ;
9229     sym_link *etype;
9230     int offset = 0 ;
9231
9232         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9233         etype = getSpec(operandType(result));
9234
9235         /* read the first byte  */
9236         switch (ptype) {
9237                 case POINTER:
9238                 case IPOINTER:
9239                 case PPOINTER:
9240                 case FPOINTER:
9241                 case GPOINTER:
9242                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9243                         break;
9244                 case CPOINTER:
9245                         pic16_emitcode("clr","a");
9246                         pic16_emitcode("movc","a","@a+dptr");
9247                         break;
9248         }
9249         
9250
9251         /* if we have bitdisplacement then it fits   */
9252         /* into this byte completely or if length is */
9253         /* less than a byte                          */
9254         if ((shCnt = SPEC_BSTR(etype)) || 
9255                 (SPEC_BLEN(etype) <= 8))  {
9256
9257                 /* shift right acc */
9258                 AccRsh(shCnt, 0);
9259
9260                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9261                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9262
9263 /* VR -- normally I would use the following, but since we use the hack,
9264  * to avoid the masking from AccRsh, why not mask it right now? */
9265
9266 /*
9267                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9268 */
9269
9270                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9271           return ;
9272         }
9273
9274
9275
9276         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9277         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9278         exit(-1);
9279
9280     /* bit field did not fit in a byte  */
9281     rlen = SPEC_BLEN(etype) - 8;
9282     pic16_aopPut(AOP(result),"a",offset++);
9283
9284     while (1)  {
9285
9286         switch (ptype) {
9287         case POINTER:
9288         case IPOINTER:
9289             pic16_emitcode("inc","%s",rname);
9290             pic16_emitcode("mov","a,@%s",rname);
9291             break;
9292             
9293         case PPOINTER:
9294             pic16_emitcode("inc","%s",rname);
9295             pic16_emitcode("movx","a,@%s",rname);
9296             break;
9297
9298         case FPOINTER:
9299             pic16_emitcode("inc","dptr");
9300             pic16_emitcode("movx","a,@dptr");
9301             break;
9302             
9303         case CPOINTER:
9304             pic16_emitcode("clr","a");
9305             pic16_emitcode("inc","dptr");
9306             pic16_emitcode("movc","a","@a+dptr");
9307             break;
9308             
9309         case GPOINTER:
9310             pic16_emitcode("inc","dptr");
9311             pic16_emitcode("lcall","__gptrget");
9312             break;
9313         }
9314
9315         rlen -= 8;            
9316         /* if we are done */
9317         if ( rlen <= 0 )
9318             break ;
9319         
9320         pic16_aopPut(AOP(result),"a",offset++);
9321                               
9322     }
9323     
9324     if (rlen) {
9325         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9326         pic16_aopPut(AOP(result),"a",offset);          
9327     }
9328     
9329     return ;
9330 }
9331
9332
9333 static void genDataPointerGet(operand *left,
9334                               operand *result,
9335                               iCode *ic)
9336 {
9337   int size, offset = 0, leoffset=0 ;
9338
9339         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9340         pic16_aopOp(result, ic, FALSE);
9341
9342         size = AOP_SIZE(result);
9343 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9344
9345
9346 #if 0
9347         /* The following tests may save a redudant movff instruction when
9348          * accessing unions */
9349          
9350         /* if they are the same */
9351         if (operandsEqu (left, result)) {
9352                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9353                 goto release;
9354         }
9355 #endif
9356
9357 #if 0
9358         /* if they are the same registers */
9359         if (pic16_sameRegs(AOP(left),AOP(result))) {
9360                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9361                 goto release;
9362         }
9363 #endif
9364
9365 #if 1
9366         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9367                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9368                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9369                 goto release;
9370         }
9371 #endif
9372
9373
9374 #if 0
9375         if ( AOP_TYPE(left) == AOP_PCODE) {
9376                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
9377                                 AOP(left)->aopu.pcop->name,
9378                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
9379                                 PCOR(AOP(left)->aopu.pcop)->instance:
9380                                 PCOI(AOP(left)->aopu.pcop)->offset);
9381         }
9382 #endif
9383
9384         if(AOP(left)->aopu.pcop->type == PO_DIR)
9385                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9386
9387         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9388
9389         while (size--) {
9390                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9391                 
9392                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9393                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9394                         mov2w(AOP(left), offset); // patch 8
9395                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9396                 } else {
9397                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9398                                 pic16_popGet(AOP(left), offset), //patch 8
9399                                 pic16_popGet(AOP(result), offset)));
9400                 }
9401
9402                 offset++;
9403                 leoffset++;
9404         }
9405
9406 release:
9407     pic16_freeAsmop(result,NULL,ic,TRUE);
9408 }
9409
9410 void pic16_loadFSR0(operand *op)
9411 {
9412         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9413 }
9414
9415
9416 /*-----------------------------------------------------------------*/
9417 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
9418 /*-----------------------------------------------------------------*/
9419 static void genNearPointerGet (operand *left, 
9420                                operand *result, 
9421                                iCode *ic)
9422 {
9423     asmop *aop = NULL;
9424     //regs *preg = NULL ;
9425     sym_link *rtype, *retype;
9426     sym_link *ltype = operandType(left);    
9427
9428         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9429         rtype = operandType(result);
9430         retype= getSpec(rtype);
9431     
9432         pic16_aopOp(left,ic,FALSE);
9433
9434 //      pic16_DumpOp("(left)",left);
9435 //      pic16_DumpOp("(result)",result);
9436
9437         /* if left is rematerialisable and
9438          * result is not bit variable type and
9439          * the left is pointer to data space i.e
9440          * lower 128 bytes of space */
9441         if (AOP_TYPE(left) == AOP_PCODE
9442                 && !IS_BITFIELD(retype)
9443                 && DCL_TYPE(ltype) == POINTER) {
9444
9445                 genDataPointerGet (left,result,ic);
9446                 pic16_freeAsmop(left, NULL, ic, TRUE);
9447           return ;
9448         }
9449     
9450         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9451
9452         /* if the value is already in a pointer register
9453          * then don't need anything more */
9454         if (!AOP_INPREG(AOP(left))) {
9455                 /* otherwise get a free pointer register */
9456                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9457                 
9458                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9459                 if( (AOP_TYPE(left) == AOP_PCODE) 
9460                         && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9461                                 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9462                 {
9463                         if(!IS_BITFIELD(retype))
9464                                 pic16_loadFSR0( left );  // patch 10
9465                 } else {
9466                         // set up FSR0 with address from left
9467                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9468                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9469                 }
9470         }
9471 //       else
9472 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9473     
9474         pic16_aopOp (result,ic,FALSE);
9475     
9476       /* if bitfield then unpack the bits */
9477     if (IS_BITFIELD(retype)) 
9478         genUnpackBits (result, left, NULL, POINTER);
9479     else {
9480         /* we have can just get the values */
9481       int size = AOP_SIZE(result);
9482       int offset = 0;   
9483         
9484       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9485
9486
9487         /* fsr0 is loaded already -- VR */
9488 //      pic16_loadFSR0( left );
9489
9490 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9491 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9492       while(size--) {
9493
9494         if(size) {
9495                 pic16_emitpcode(POC_MOVFF,
9496                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9497                                 pic16_popGet(AOP(result), offset++)));
9498         } else {
9499                 pic16_emitpcode(POC_MOVFF,
9500                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9501                                 pic16_popGet(AOP(result), offset++)));
9502         }
9503       }
9504 #if 0
9505 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9506 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9507         if(size)
9508           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9509 #endif
9510 /*
9511         while (size--) {
9512             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9513
9514                 pic16_emitcode("mov","a,@%s",rname);
9515                 pic16_aopPut(AOP(result),"a",offset);
9516             } else {
9517                 sprintf(buffer,"@%s",rname);
9518                 pic16_aopPut(AOP(result),buffer,offset);
9519             }
9520             offset++ ;
9521             if (size)
9522                 pic16_emitcode("inc","%s",rname);
9523         }
9524 */
9525     }
9526
9527     /* now some housekeeping stuff */
9528     if (aop) {
9529         /* we had to allocate for this iCode */
9530     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9531         pic16_freeAsmop(NULL,aop,ic,TRUE);
9532     } else { 
9533         /* we did not allocate which means left
9534            already in a pointer register, then
9535            if size > 0 && this could be used again
9536            we have to point it back to where it 
9537            belongs */
9538     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9539         if (AOP_SIZE(result) > 1 &&
9540             !OP_SYMBOL(left)->remat &&
9541             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9542               ic->depth )) {
9543 //          int size = AOP_SIZE(result) - 1;
9544 //          while (size--)
9545 //              pic16_emitcode("dec","%s",rname);
9546         }
9547     }
9548
9549     /* done */
9550     pic16_freeAsmop(left,NULL,ic,TRUE);
9551     pic16_freeAsmop(result,NULL,ic,TRUE);
9552      
9553 }
9554
9555 /*-----------------------------------------------------------------*/
9556 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
9557 /*-----------------------------------------------------------------*/
9558 static void genPagedPointerGet (operand *left, 
9559                                operand *result, 
9560                                iCode *ic)
9561 {
9562     asmop *aop = NULL;
9563     regs *preg = NULL ;
9564     char *rname ;
9565     sym_link *rtype, *retype;    
9566
9567     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9568
9569     rtype = operandType(result);
9570     retype= getSpec(rtype);
9571     
9572     pic16_aopOp(left,ic,FALSE);
9573
9574   /* if the value is already in a pointer register
9575        then don't need anything more */
9576     if (!AOP_INPREG(AOP(left))) {
9577         /* otherwise get a free pointer register */
9578         aop = newAsmop(0);
9579         preg = getFreePtr(ic,&aop,FALSE);
9580         pic16_emitcode("mov","%s,%s",
9581                 preg->name,
9582                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9583         rname = preg->name ;
9584     } else
9585         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9586     
9587     pic16_freeAsmop(left,NULL,ic,TRUE);
9588     pic16_aopOp (result,ic,FALSE);
9589
9590     /* if bitfield then unpack the bits */
9591     if (IS_BITFIELD(retype)) 
9592         genUnpackBits (result,left,rname,PPOINTER);
9593     else {
9594         /* we have can just get the values */
9595         int size = AOP_SIZE(result);
9596         int offset = 0 ;        
9597         
9598         while (size--) {
9599             
9600             pic16_emitcode("movx","a,@%s",rname);
9601             pic16_aopPut(AOP(result),"a",offset);
9602             
9603             offset++ ;
9604             
9605             if (size)
9606                 pic16_emitcode("inc","%s",rname);
9607         }
9608     }
9609
9610     /* now some housekeeping stuff */
9611     if (aop) {
9612         /* we had to allocate for this iCode */
9613         pic16_freeAsmop(NULL,aop,ic,TRUE);
9614     } else { 
9615         /* we did not allocate which means left
9616            already in a pointer register, then
9617            if size > 0 && this could be used again
9618            we have to point it back to where it 
9619            belongs */
9620         if (AOP_SIZE(result) > 1 &&
9621             !OP_SYMBOL(left)->remat &&
9622             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9623               ic->depth )) {
9624             int size = AOP_SIZE(result) - 1;
9625             while (size--)
9626                 pic16_emitcode("dec","%s",rname);
9627         }
9628     }
9629
9630     /* done */
9631     pic16_freeAsmop(result,NULL,ic,TRUE);
9632     
9633         
9634 }
9635
9636 /*-----------------------------------------------------------------*/
9637 /* genFarPointerGet - gget value from far space                    */
9638 /*-----------------------------------------------------------------*/
9639 static void genFarPointerGet (operand *left,
9640                               operand *result, iCode *ic)
9641 {
9642     int size, offset ;
9643     sym_link *retype = getSpec(operandType(result));
9644
9645     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9646
9647     pic16_aopOp(left,ic,FALSE);
9648
9649     /* if the operand is already in dptr 
9650     then we do nothing else we move the value to dptr */
9651     if (AOP_TYPE(left) != AOP_STR) {
9652         /* if this is remateriazable */
9653         if (AOP_TYPE(left) == AOP_IMMD)
9654             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9655         else { /* we need to get it byte by byte */
9656             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9657             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9658             if (options.model == MODEL_FLAT24)
9659             {
9660                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9661             }
9662         }
9663     }
9664     /* so dptr know contains the address */
9665     pic16_freeAsmop(left,NULL,ic,TRUE);
9666     pic16_aopOp(result,ic,FALSE);
9667
9668     /* if bit then unpack */
9669     if (IS_BITFIELD(retype)) 
9670         genUnpackBits(result,left,"dptr",FPOINTER);
9671     else {
9672         size = AOP_SIZE(result);
9673         offset = 0 ;
9674
9675         while (size--) {
9676             pic16_emitcode("movx","a,@dptr");
9677             pic16_aopPut(AOP(result),"a",offset++);
9678             if (size)
9679                 pic16_emitcode("inc","dptr");
9680         }
9681     }
9682
9683     pic16_freeAsmop(result,NULL,ic,TRUE);
9684 }
9685 #if 0
9686 /*-----------------------------------------------------------------*/
9687 /* genCodePointerGet - get value from code space                  */
9688 /*-----------------------------------------------------------------*/
9689 static void genCodePointerGet (operand *left,
9690                                 operand *result, iCode *ic)
9691 {
9692     int size, offset ;
9693     sym_link *retype = getSpec(operandType(result));
9694
9695     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9696
9697     pic16_aopOp(left,ic,FALSE);
9698
9699     /* if the operand is already in dptr 
9700     then we do nothing else we move the value to dptr */
9701     if (AOP_TYPE(left) != AOP_STR) {
9702         /* if this is remateriazable */
9703         if (AOP_TYPE(left) == AOP_IMMD)
9704             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9705         else { /* we need to get it byte by byte */
9706             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9707             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9708             if (options.model == MODEL_FLAT24)
9709             {
9710                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9711             }
9712         }
9713     }
9714     /* so dptr know contains the address */
9715     pic16_freeAsmop(left,NULL,ic,TRUE);
9716     pic16_aopOp(result,ic,FALSE);
9717
9718     /* if bit then unpack */
9719     if (IS_BITFIELD(retype)) 
9720         genUnpackBits(result,left,"dptr",CPOINTER);
9721     else {
9722         size = AOP_SIZE(result);
9723         offset = 0 ;
9724
9725         while (size--) {
9726             pic16_emitcode("clr","a");
9727             pic16_emitcode("movc","a,@a+dptr");
9728             pic16_aopPut(AOP(result),"a",offset++);
9729             if (size)
9730                 pic16_emitcode("inc","dptr");
9731         }
9732     }
9733
9734     pic16_freeAsmop(result,NULL,ic,TRUE);
9735 }
9736 #endif
9737 /*-----------------------------------------------------------------*/
9738 /* genGenPointerGet - gget value from generic pointer space        */
9739 /*-----------------------------------------------------------------*/
9740 static void genGenPointerGet (operand *left,
9741                               operand *result, iCode *ic)
9742 {
9743   int size, offset, lit;
9744   sym_link *retype = getSpec(operandType(result));
9745
9746         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9747         pic16_aopOp(left,ic,FALSE);
9748         pic16_aopOp(result,ic,FALSE);
9749         size = AOP_SIZE(result);
9750
9751         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9752
9753         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9754
9755                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9756                 // load FSR0 from immediate
9757                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9758
9759 //              pic16_loadFSR0( left );
9760
9761                 offset = 0;
9762                 while(size--) {
9763                         if(size) {
9764                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9765                         } else {
9766                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9767                         }
9768                         offset++;
9769                 }
9770                 goto release;
9771
9772         }
9773         else { /* we need to get it byte by byte */
9774                 // set up FSR0 with address from left
9775                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9776                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9777
9778                 offset = 0 ;
9779
9780                 while(size--) {
9781                         if(size) {
9782                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9783                         } else {
9784                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9785                         }
9786                         offset++;
9787                 }
9788                 goto release;
9789         }
9790
9791   /* if bit then unpack */
9792         if (IS_BITFIELD(retype)) 
9793                 genUnpackBits(result,left,"BAD",GPOINTER);
9794
9795         release:
9796         pic16_freeAsmop(left,NULL,ic,TRUE);
9797         pic16_freeAsmop(result,NULL,ic,TRUE);
9798
9799 }
9800
9801 /*-----------------------------------------------------------------*/
9802 /* genConstPointerGet - get value from const generic pointer space */
9803 /*-----------------------------------------------------------------*/
9804 static void genConstPointerGet (operand *left,
9805                                 operand *result, iCode *ic)
9806 {
9807   //sym_link *retype = getSpec(operandType(result));
9808   // symbol *albl = newiTempLabel(NULL);        // patch 15
9809   // symbol *blbl = newiTempLabel(NULL);        //
9810   // PIC_OPCODE poc;                            // patch 15
9811   int size;
9812   int offset = 0;
9813
9814   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9815   pic16_aopOp(left,ic,FALSE);
9816   pic16_aopOp(result,ic,TRUE);
9817   size = AOP_SIZE(result);
9818
9819   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9820
9821   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9822 #if 0                                                                   // patch 15
9823   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9824   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9825   pic16_emitpLabel(albl->key);
9826
9827   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9828     
9829   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9830   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9831   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9832   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9833   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9834
9835   pic16_emitpLabel(blbl->key);
9836
9837   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9838 #endif                                                                  // patch 15
9839
9840
9841   // set up table pointer
9842   if( (AOP_TYPE(left) == AOP_PCODE) 
9843       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9844           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
9845     {
9846       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9847       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9848       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9849       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9850       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9851       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9852     }
9853   else
9854     {
9855       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9856       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9857       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9858     }
9859
9860
9861   while(size--)
9862     {
9863       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9864       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9865       offset++;
9866     }
9867     
9868   pic16_freeAsmop(left,NULL,ic,TRUE);
9869   pic16_freeAsmop(result,NULL,ic,TRUE);
9870
9871 }
9872
9873
9874 /*-----------------------------------------------------------------*/
9875 /* genPointerGet - generate code for pointer get                   */
9876 /*-----------------------------------------------------------------*/
9877 static void genPointerGet (iCode *ic)
9878 {
9879     operand *left, *result ;
9880     sym_link *type, *etype;
9881     int p_type;
9882
9883     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9884
9885     left = IC_LEFT(ic);
9886     result = IC_RESULT(ic) ;
9887
9888     /* depending on the type of pointer we need to
9889     move it to the correct pointer register */
9890     type = operandType(left);
9891     etype = getSpec(type);
9892
9893 #if 0
9894     if (IS_PTR_CONST(type))
9895 #else
9896     if (IS_CODEPTR(type))
9897 #endif
9898       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9899
9900     /* if left is of type of pointer then it is simple */
9901     if (IS_PTR(type) && !IS_FUNC(type->next)) 
9902         p_type = DCL_TYPE(type);
9903     else {
9904         /* we have to go by the storage class */
9905         p_type = PTR_TYPE(SPEC_OCLS(etype));
9906
9907         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9908
9909         if (SPEC_OCLS(etype)->codesp ) {
9910           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9911           //p_type = CPOINTER ; 
9912         }
9913         else
9914             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9915               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9916                /*p_type = FPOINTER ;*/ 
9917             else
9918                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9919                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9920 /*                  p_type = PPOINTER; */
9921                 else
9922                     if (SPEC_OCLS(etype) == idata )
9923                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9924 /*                      p_type = IPOINTER; */
9925                     else
9926                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9927 /*                      p_type = POINTER ; */
9928     }
9929
9930     /* now that we have the pointer type we assign
9931     the pointer values */
9932     switch (p_type) {
9933
9934     case POINTER:       
9935     case IPOINTER:
9936         genNearPointerGet (left,result,ic);
9937         break;
9938
9939     case PPOINTER:
9940         genPagedPointerGet(left,result,ic);
9941         break;
9942
9943     case FPOINTER:
9944         genFarPointerGet (left,result,ic);
9945         break;
9946
9947     case CPOINTER:
9948         genConstPointerGet (left,result,ic);
9949         //pic16_emitcodePointerGet (left,result,ic);
9950         break;
9951
9952     case GPOINTER:
9953 #if 0
9954       if (IS_PTR_CONST(type))
9955         genConstPointerGet (left,result,ic);
9956       else
9957 #endif
9958         genGenPointerGet (left,result,ic);
9959       break;
9960
9961     default:
9962       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9963               "genPointerGet: illegal pointer type");
9964     
9965     }
9966
9967 }
9968
9969 /*-----------------------------------------------------------------*/
9970 /* genPackBits - generates code for packed bit storage             */
9971 /*-----------------------------------------------------------------*/
9972 static void genPackBits (sym_link    *etype , operand *result,
9973                          operand *right ,
9974                          char *rname, int p_type)
9975 {
9976   int shCnt = 0 ;
9977   int offset = 0  ;
9978   int rLen = 0 ;
9979   int blen, bstr ;   
9980   char *l ;
9981
9982         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9983         blen = SPEC_BLEN(etype);
9984         bstr = SPEC_BSTR(etype);
9985
9986         if(AOP_TYPE(right) == AOP_LIT) {
9987                 if((blen == 1) && (bstr < 8)) {
9988                   unsigned long lit;
9989                         /* it is a single bit, so use the appropriate bit instructions */
9990
9991                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
9992
9993                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9994 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9995                         if((p_type == POINTER) && (result)) {
9996                                 /* workaround to reduce the extra lfsr instruction */
9997                                 if(lit) {
9998                                         pic16_emitpcode(POC_BSF,
9999                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
10000                                 } else {
10001                                         pic16_emitpcode(POC_BCF,
10002                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
10003                                 }
10004                         } else {
10005
10006                                 if(lit) {
10007                                         pic16_emitpcode(POC_BSF,
10008                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10009                                 } else {
10010                                         pic16_emitpcode(POC_BCF,
10011                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10012                                 }
10013                         }
10014         
10015                   return;
10016                 }
10017
10018                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
10019                 offset++;
10020         } else
10021                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
10022
10023         /* if the bit lenth is less than or    */
10024         /* it exactly fits a byte then         */
10025         if((shCnt=SPEC_BSTR(etype))
10026                 || SPEC_BLEN(etype) <= 8 )  {
10027
10028                 /* shift left acc */
10029                 AccLsh(shCnt);
10030
10031                 /* using PRODL as a temporary register here */
10032                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
10033
10034                 switch (p_type) {
10035                         case FPOINTER:
10036                         case POINTER:
10037                         case GPOINTER:
10038                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10039 //                              pic16_emitcode ("mov","b,a");
10040 //                              pic16_emitcode("mov","a,@%s",rname);
10041                                 break;
10042                 }
10043 #if 1
10044                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10045                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
10046                                         (unsigned char)(0xff >> (8-bstr))) ));
10047                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
10048                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10049 #endif
10050
10051           return;
10052         }
10053
10054
10055         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10056         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10057         exit(-1);
10058
10059
10060     /* if we r done */
10061     if ( SPEC_BLEN(etype) <= 8 )
10062         return ;
10063
10064     pic16_emitcode("inc","%s",rname);
10065     rLen = SPEC_BLEN(etype) ;     
10066
10067
10068
10069     /* now generate for lengths greater than one byte */
10070     while (1) {
10071
10072         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
10073
10074         rLen -= 8 ;
10075         if (rLen <= 0 )
10076             break ;
10077
10078         switch (p_type) {
10079             case POINTER:
10080                 if (*l == '@') {
10081                     MOVA(l);
10082                     pic16_emitcode("mov","@%s,a",rname);
10083                 } else
10084                     pic16_emitcode("mov","@%s,%s",rname,l);
10085                 break;
10086
10087             case FPOINTER:
10088                 MOVA(l);
10089                 pic16_emitcode("movx","@dptr,a");
10090                 break;
10091
10092             case GPOINTER:
10093                 MOVA(l);
10094                 DEBUGpic16_emitcode(";lcall","__gptrput");
10095                 break;  
10096         }   
10097         pic16_emitcode ("inc","%s",rname);
10098     }
10099
10100     MOVA(l);
10101
10102     /* last last was not complete */
10103     if (rLen)   {
10104         /* save the byte & read byte */
10105         switch (p_type) {
10106             case POINTER:
10107                 pic16_emitcode ("mov","b,a");
10108                 pic16_emitcode("mov","a,@%s",rname);
10109                 break;
10110
10111             case FPOINTER:
10112                 pic16_emitcode ("mov","b,a");
10113                 pic16_emitcode("movx","a,@dptr");
10114                 break;
10115
10116             case GPOINTER:
10117                 pic16_emitcode ("push","b");
10118                 pic16_emitcode ("push","acc");
10119                 pic16_emitcode ("lcall","__gptrget");
10120                 pic16_emitcode ("pop","b");
10121                 break;
10122         }
10123
10124         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
10125         pic16_emitcode ("orl","a,b");
10126     }
10127
10128     if (p_type == GPOINTER)
10129         pic16_emitcode("pop","b");
10130
10131     switch (p_type) {
10132
10133     case POINTER:
10134         pic16_emitcode("mov","@%s,a",rname);
10135         break;
10136         
10137     case FPOINTER:
10138         pic16_emitcode("movx","@dptr,a");
10139         break;
10140         
10141     case GPOINTER:
10142         DEBUGpic16_emitcode(";lcall","__gptrput");
10143         break;                  
10144     }
10145 }
10146 /*-----------------------------------------------------------------*/
10147 /* genDataPointerSet - remat pointer to data space                 */
10148 /*-----------------------------------------------------------------*/
10149 static void genDataPointerSet(operand *right,
10150                               operand *result,
10151                               iCode *ic)
10152 {
10153     int size, offset = 0, resoffset=0 ;
10154
10155     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10156     pic16_aopOp(right,ic,FALSE);
10157
10158     size = AOP_SIZE(right);
10159
10160 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10161
10162 #if 0
10163     if ( AOP_TYPE(result) == AOP_PCODE) {
10164       fprintf(stderr,"genDataPointerSet   %s, %d\n",
10165               AOP(result)->aopu.pcop->name,
10166                 (AOP(result)->aopu.pcop->type == PO_DIR)?
10167               PCOR(AOP(result)->aopu.pcop)->instance:
10168               PCOI(AOP(result)->aopu.pcop)->offset);
10169     }
10170 #endif
10171
10172         if(AOP(result)->aopu.pcop->type == PO_DIR)
10173                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
10174
10175         while (size--) {
10176                 if (AOP_TYPE(right) == AOP_LIT) {
10177                   unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
10178
10179                         lit = lit >> (8*offset);
10180                         if(lit&0xff) {
10181                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
10182                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
10183                         } else {
10184                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
10185                         }
10186                 } else {
10187                         mov2w(AOP(right), offset);
10188                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
10189                 }
10190                 offset++;
10191                 resoffset++;
10192         }
10193
10194     pic16_freeAsmop(right,NULL,ic,TRUE);
10195 }
10196
10197
10198
10199 /*-----------------------------------------------------------------*/
10200 /* genNearPointerSet - pic16_emitcode for near pointer put         */
10201 /*-----------------------------------------------------------------*/
10202 static void genNearPointerSet (operand *right,
10203                                operand *result, 
10204                                iCode *ic)
10205 {
10206   asmop *aop = NULL;
10207   char *l;
10208   sym_link *retype;
10209   sym_link *ptype = operandType(result);
10210   sym_link *resetype;
10211     
10212         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10213         retype= getSpec(operandType(right));
10214         resetype = getSpec(operandType(result));
10215   
10216         pic16_aopOp(result,ic,FALSE);
10217     
10218         /* if the result is rematerializable &
10219          * in data space & not a bit variable */
10220         
10221         /* and result is not a bit variable */
10222         if (AOP_TYPE(result) == AOP_PCODE
10223 //              && AOP_TYPE(result) == AOP_IMMD
10224                 && DCL_TYPE(ptype) == POINTER
10225                 && !IS_BITFIELD(retype)
10226                 && !IS_BITFIELD(resetype)) {
10227
10228                 genDataPointerSet (right,result,ic);
10229                 pic16_freeAsmop(result,NULL,ic,TRUE);
10230           return;
10231         }
10232
10233         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10234         pic16_aopOp(right,ic,FALSE);
10235         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10236
10237         /* if the value is already in a pointer register
10238          * then don't need anything more */
10239         if (!AOP_INPREG(AOP(result))) {
10240                 /* otherwise get a free pointer register */
10241                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10242
10243                 if( (AOP_TYPE(result) == AOP_PCODE) 
10244                         && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10245                                 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10246                 {
10247                   if(!IS_BITFIELD(resetype))
10248                         pic16_loadFSR0( result );  // patch 10
10249                 } else {
10250                         // set up FSR0 with address of result
10251                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10252                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10253                 }
10254
10255         }
10256 //      else
10257 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10258
10259         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10260
10261         /* if bitfield then unpack the bits */
10262         if (IS_BITFIELD(resetype)) {
10263                 genPackBits (resetype, result, right, NULL, POINTER);
10264         } else {
10265                 /* we have can just get the values */
10266           int size = AOP_SIZE(right);
10267           int offset = 0 ;    
10268
10269                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10270                 while (size--) {
10271                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10272                         if (*l == '@' ) {
10273                                 //MOVA(l);
10274                                 //pic16_emitcode("mov","@%s,a",rname);
10275                                 pic16_emitcode("movf","indf0,w ;1");
10276                         } else {
10277
10278                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
10279                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
10280                                         if (size) {                                                                     // 
10281                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
10282                                         } else {                                                                        // 
10283                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
10284                                         }                                                                               // 
10285                                 } else { // no literal                                                                  // 
10286                                         if(size) {                                                                      // 
10287                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10288                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10289                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
10290                                         } else {                                                                        // 
10291                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10292                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10293                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
10294                                         }                                                                               //
10295                                 }                                                                                       // patch 10
10296                         }
10297                         offset++;
10298                 }
10299         }
10300
10301         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10302         /* now some housekeeping stuff */
10303         if (aop) {
10304                 /* we had to allocate for this iCode */
10305                 pic16_freeAsmop(NULL,aop,ic,TRUE);
10306         } else { 
10307                 /* we did not allocate which means left
10308                  * already in a pointer register, then
10309                  * if size > 0 && this could be used again
10310                  * we have to point it back to where it 
10311                  * belongs */
10312                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10313                 if (AOP_SIZE(right) > 1
10314                         && !OP_SYMBOL(result)->remat
10315                         && ( OP_SYMBOL(result)->liveTo > ic->seq
10316                                 || ic->depth )) {
10317
10318                   int size = AOP_SIZE(right) - 1;
10319
10320                         while (size--)
10321                                 pic16_emitcode("decf","fsr0,f");
10322                         //pic16_emitcode("dec","%s",rname);
10323                 }
10324         }
10325
10326         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10327         /* done */
10328 //release:
10329         pic16_freeAsmop(right,NULL,ic,TRUE);
10330         pic16_freeAsmop(result,NULL,ic,TRUE);
10331 }
10332
10333 /*-----------------------------------------------------------------*/
10334 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
10335 /*-----------------------------------------------------------------*/
10336 static void genPagedPointerSet (operand *right,
10337                                operand *result, 
10338                                iCode *ic)
10339 {
10340     asmop *aop = NULL;
10341     regs *preg = NULL ;
10342     char *rname , *l;
10343     sym_link *retype;
10344        
10345     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10346
10347     retype= getSpec(operandType(right));
10348     
10349     pic16_aopOp(result,ic,FALSE);
10350     
10351     /* if the value is already in a pointer register
10352        then don't need anything more */
10353     if (!AOP_INPREG(AOP(result))) {
10354         /* otherwise get a free pointer register */
10355         aop = newAsmop(0);
10356         preg = getFreePtr(ic,&aop,FALSE);
10357         pic16_emitcode("mov","%s,%s",
10358                 preg->name,
10359                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10360         rname = preg->name ;
10361     } else
10362         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10363     
10364     pic16_freeAsmop(result,NULL,ic,TRUE);
10365     pic16_aopOp (right,ic,FALSE);
10366
10367     /* if bitfield then unpack the bits */
10368     if (IS_BITFIELD(retype)) 
10369         genPackBits (retype,result,right,rname,PPOINTER);
10370     else {
10371         /* we have can just get the values */
10372         int size = AOP_SIZE(right);
10373         int offset = 0 ;        
10374         
10375         while (size--) {
10376             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10377             
10378             MOVA(l);
10379             pic16_emitcode("movx","@%s,a",rname);
10380
10381             if (size)
10382                 pic16_emitcode("inc","%s",rname);
10383
10384             offset++;
10385         }
10386     }
10387     
10388     /* now some housekeeping stuff */
10389     if (aop) {
10390         /* we had to allocate for this iCode */
10391         pic16_freeAsmop(NULL,aop,ic,TRUE);
10392     } else { 
10393         /* we did not allocate which means left
10394            already in a pointer register, then
10395            if size > 0 && this could be used again
10396            we have to point it back to where it 
10397            belongs */
10398         if (AOP_SIZE(right) > 1 &&
10399             !OP_SYMBOL(result)->remat &&
10400             ( OP_SYMBOL(result)->liveTo > ic->seq ||
10401               ic->depth )) {
10402             int size = AOP_SIZE(right) - 1;
10403             while (size--)
10404                 pic16_emitcode("dec","%s",rname);
10405         }
10406     }
10407
10408     /* done */
10409     pic16_freeAsmop(right,NULL,ic,TRUE);
10410     
10411         
10412 }
10413
10414 /*-----------------------------------------------------------------*/
10415 /* genFarPointerSet - set value from far space                     */
10416 /*-----------------------------------------------------------------*/
10417 static void genFarPointerSet (operand *right,
10418                               operand *result, iCode *ic)
10419 {
10420     int size, offset ;
10421     sym_link *retype = getSpec(operandType(right));
10422
10423     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10424     pic16_aopOp(result,ic,FALSE);
10425
10426     /* if the operand is already in dptr 
10427     then we do nothing else we move the value to dptr */
10428     if (AOP_TYPE(result) != AOP_STR) {
10429         /* if this is remateriazable */
10430         if (AOP_TYPE(result) == AOP_IMMD)
10431             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10432         else { /* we need to get it byte by byte */
10433             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10434             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10435             if (options.model == MODEL_FLAT24)
10436             {
10437                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10438             }
10439         }
10440     }
10441     /* so dptr know contains the address */
10442     pic16_freeAsmop(result,NULL,ic,TRUE);
10443     pic16_aopOp(right,ic,FALSE);
10444
10445     /* if bit then unpack */
10446     if (IS_BITFIELD(retype)) 
10447         genPackBits(retype,result,right,"dptr",FPOINTER);
10448     else {
10449         size = AOP_SIZE(right);
10450         offset = 0 ;
10451
10452         while (size--) {
10453             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10454             MOVA(l);
10455             pic16_emitcode("movx","@dptr,a");
10456             if (size)
10457                 pic16_emitcode("inc","dptr");
10458         }
10459     }
10460
10461     pic16_freeAsmop(right,NULL,ic,TRUE);
10462 }
10463
10464 /*-----------------------------------------------------------------*/
10465 /* genGenPointerSet - set value from generic pointer space         */
10466 /*-----------------------------------------------------------------*/
10467 static void genGenPointerSet (operand *right,
10468                               operand *result, iCode *ic)
10469 {
10470         int i, size, offset, lit;
10471         sym_link *retype = getSpec(operandType(right));
10472
10473         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10474
10475         pic16_aopOp(result,ic,FALSE);
10476         pic16_aopOp(right,ic,FALSE);
10477         size = AOP_SIZE(right);
10478         offset = 0;
10479
10480         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10481
10482         /* if the operand is already in dptr 
10483                 then we do nothing else we move the value to dptr */
10484         if (AOP_TYPE(result) != AOP_STR) {
10485                 /* if this is remateriazable */
10486                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10487                 // WARNING: anythig until "else" is untested!
10488                 if (AOP_TYPE(result) == AOP_IMMD) {
10489                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10490                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10491                         // load FSR0 from immediate
10492                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10493                         offset = 0;
10494                         while(size--) {
10495                                 if(size) {
10496                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10497                                 } else {
10498                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10499                                 }
10500                                 offset++;
10501                         }
10502                         goto release;
10503                 }
10504                 else { /* we need to get it byte by byte */
10505                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10506                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10507
10508                         // set up FSR0 with address of result
10509                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10510                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10511
10512                         /* hack hack! see if this the FSR. If so don't load W */
10513                         if(AOP_TYPE(right) != AOP_ACC) {
10514
10515                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10516
10517                                 if(AOP_TYPE(right) == AOP_LIT)
10518                                 {
10519                                         // copy literal
10520                                         // note: pic16_popGet handles sign extension
10521                                         for(i=0;i<size;i++) {
10522                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10523                                                 if(i < size-1)
10524                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10525                                                 else
10526                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10527                                         }
10528                                 } else {
10529                                         // copy regs
10530
10531                                         for(i=0;i<size;i++) {
10532                                                 if(i < size-1)
10533                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10534                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
10535                                                 else
10536                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10537                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
10538                                         }
10539                                 }
10540                                 goto release;
10541                         } 
10542                         // right = ACC
10543                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10544                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10545                         goto release;
10546         } // if (AOP_TYPE(result) != AOP_IMMD)
10547
10548         } // if (AOP_TYPE(result) != AOP_STR)
10549         /* so dptr know contains the address */
10550
10551
10552         /* if bit then unpack */
10553         if (IS_BITFIELD(retype)) 
10554                 genPackBits(retype,result,right,"dptr",GPOINTER);
10555         else {
10556                 size = AOP_SIZE(right);
10557                 offset = 0 ;
10558
10559                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
10560
10561                 // set up FSR0 with address of result
10562                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10563                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10564         
10565                 while (size--) {
10566                         if (AOP_TYPE(right) == AOP_LIT) {
10567                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10568                                 if (size) {
10569                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10570                                 } else {
10571                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10572                                 }
10573                         } else { // no literal
10574                                 if(size) {
10575                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10576                                 } else {
10577                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10578                                 }
10579                         }
10580                         offset++;
10581                 }
10582         }
10583
10584         release:
10585         pic16_freeAsmop(right,NULL,ic,TRUE);
10586         pic16_freeAsmop(result,NULL,ic,TRUE);
10587 }
10588
10589 /*-----------------------------------------------------------------*/
10590 /* genPointerSet - stores the value into a pointer location        */
10591 /*-----------------------------------------------------------------*/
10592 static void genPointerSet (iCode *ic)
10593 {    
10594     operand *right, *result ;
10595     sym_link *type, *etype;
10596     int p_type;
10597
10598     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10599
10600     right = IC_RIGHT(ic);
10601     result = IC_RESULT(ic) ;
10602
10603     /* depending on the type of pointer we need to
10604     move it to the correct pointer register */
10605     type = operandType(result);
10606     etype = getSpec(type);
10607     /* if left is of type of pointer then it is simple */
10608     if (IS_PTR(type) && !IS_FUNC(type->next)) {
10609         p_type = DCL_TYPE(type);
10610     }
10611     else {
10612         /* we have to go by the storage class */
10613         p_type = PTR_TYPE(SPEC_OCLS(etype));
10614
10615 /*      if (SPEC_OCLS(etype)->codesp ) { */
10616 /*          p_type = CPOINTER ;  */
10617 /*      } */
10618 /*      else */
10619 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10620 /*              p_type = FPOINTER ; */
10621 /*          else */
10622 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10623 /*                  p_type = PPOINTER ; */
10624 /*              else */
10625 /*                  if (SPEC_OCLS(etype) == idata ) */
10626 /*                      p_type = IPOINTER ; */
10627 /*                  else */
10628 /*                      p_type = POINTER ; */
10629     }
10630
10631     /* now that we have the pointer type we assign
10632     the pointer values */
10633     switch (p_type) {
10634
10635     case POINTER:
10636     case IPOINTER:
10637         genNearPointerSet (right,result,ic);
10638         break;
10639
10640     case PPOINTER:
10641         genPagedPointerSet (right,result,ic);
10642         break;
10643
10644     case FPOINTER:
10645         genFarPointerSet (right,result,ic);
10646         break;
10647
10648     case GPOINTER:
10649         genGenPointerSet (right,result,ic);
10650         break;
10651
10652     default:
10653       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10654               "genPointerSet: illegal pointer type");
10655     }
10656 }
10657
10658 /*-----------------------------------------------------------------*/
10659 /* genIfx - generate code for Ifx statement                        */
10660 /*-----------------------------------------------------------------*/
10661 static void genIfx (iCode *ic, iCode *popIc)
10662 {
10663   operand *cond = IC_COND(ic);
10664   int isbit =0;
10665
10666   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10667
10668   pic16_aopOp(cond,ic,FALSE);
10669
10670   /* get the value into acc */
10671   if (AOP_TYPE(cond) != AOP_CRY)
10672     pic16_toBoolean(cond);
10673   else
10674     isbit = 1;
10675   /* the result is now in the accumulator */
10676   pic16_freeAsmop(cond,NULL,ic,TRUE);
10677
10678   /* if there was something to be popped then do it */
10679   if (popIc)
10680     genIpop(popIc);
10681
10682   /* if the condition is  a bit variable */
10683   if (isbit && IS_ITEMP(cond) && 
10684       SPIL_LOC(cond)) {
10685     genIfxJump(ic,SPIL_LOC(cond)->rname);
10686     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10687   }
10688   else {
10689     if (isbit && !IS_ITEMP(cond))
10690       genIfxJump(ic,OP_SYMBOL(cond)->rname);
10691     else
10692       genIfxJump(ic,"a");
10693   }
10694   ic->generated = 1;
10695
10696 }
10697
10698 /*-----------------------------------------------------------------*/
10699 /* genAddrOf - generates code for address of                       */
10700 /*-----------------------------------------------------------------*/
10701 static void genAddrOf (iCode *ic)
10702 {
10703   operand *result, *left;
10704   int size;
10705   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
10706   pCodeOp *pcop0, *pcop1, *pcop2;
10707
10708         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10709
10710         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10711         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10712
10713         sym = OP_SYMBOL( left );
10714
10715         size = AOP_SIZE(IC_RESULT(ic));
10716
10717
10718         if(sym->onStack) {
10719                 DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
10720         
10721                 return;
10722         }
10723         
10724 //      if(pic16_debug_verbose) {
10725 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10726 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10727 //      }
10728         
10729         /* Assume that what we want the address of is in data space
10730          * since there is no stack on the PIC, yet! -- VR */
10731         /* low */
10732         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10733
10734         /* high */
10735         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10736         
10737         /* upper */
10738         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10739         
10740
10741         if (size == 3) {
10742                 pic16_emitpcode(POC_MOVLW, pcop0);
10743                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10744                 pic16_emitpcode(POC_MOVLW, pcop1);
10745                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10746                 pic16_emitpcode(POC_MOVLW, pcop2);
10747                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10748         } else
10749         if (size == 2) {
10750                 pic16_emitpcode(POC_MOVLW, pcop0);
10751                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10752                 pic16_emitpcode(POC_MOVLW, pcop1);
10753                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10754         } else {
10755                 pic16_emitpcode(POC_MOVLW, pcop0);
10756                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10757         }
10758
10759         pic16_freeAsmop(result,NULL,ic,TRUE);
10760         pic16_freeAsmop(left, NULL, ic, FALSE);
10761 }
10762
10763
10764 #if 0
10765 /*-----------------------------------------------------------------*/
10766 /* genFarFarAssign - assignment when both are in far space         */
10767 /*-----------------------------------------------------------------*/
10768 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10769 {
10770     int size = AOP_SIZE(right);
10771     int offset = 0;
10772     char *l ;
10773     /* first push the right side on to the stack */
10774     while (size--) {
10775         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10776         MOVA(l);
10777         pic16_emitcode ("push","acc");
10778     }
10779     
10780     pic16_freeAsmop(right,NULL,ic,FALSE);
10781     /* now assign DPTR to result */
10782     pic16_aopOp(result,ic,FALSE);
10783     size = AOP_SIZE(result);
10784     while (size--) {
10785         pic16_emitcode ("pop","acc");
10786         pic16_aopPut(AOP(result),"a",--offset);
10787     }
10788     pic16_freeAsmop(result,NULL,ic,FALSE);
10789         
10790 }
10791 #endif
10792
10793 /*-----------------------------------------------------------------*/
10794 /* genAssign - generate code for assignment                        */
10795 /*-----------------------------------------------------------------*/
10796 static void genAssign (iCode *ic)
10797 {
10798   operand *result, *right;
10799   int size, offset,know_W;
10800   unsigned long lit = 0L;
10801
10802   result = IC_RESULT(ic);
10803   right  = IC_RIGHT(ic) ;
10804
10805   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10806   
10807   /* if they are the same */
10808   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10809     return ;
10810
10811   pic16_aopOp(right,ic,FALSE);
10812   pic16_aopOp(result,ic,TRUE);
10813
10814   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10815
10816   /* if they are the same registers */
10817   if (pic16_sameRegs(AOP(right),AOP(result)))
10818     goto release;
10819
10820   /* if the result is a bit */
10821   if (AOP_TYPE(result) == AOP_CRY) {
10822     /* if the right size is a literal then
10823        we know what the value is */
10824     if (AOP_TYPE(right) == AOP_LIT) {
10825           
10826       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10827                   pic16_popGet(AOP(result),0));
10828
10829       if (((int) operandLitValue(right))) 
10830         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10831                        AOP(result)->aopu.aop_dir,
10832                        AOP(result)->aopu.aop_dir);
10833       else
10834         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10835                        AOP(result)->aopu.aop_dir,
10836                        AOP(result)->aopu.aop_dir);
10837       goto release;
10838     }
10839
10840     /* the right is also a bit variable */
10841     if (AOP_TYPE(right) == AOP_CRY) {
10842       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10843       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10844       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10845
10846       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10847                      AOP(result)->aopu.aop_dir,
10848                      AOP(result)->aopu.aop_dir);
10849       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10850                      AOP(right)->aopu.aop_dir,
10851                      AOP(right)->aopu.aop_dir);
10852       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10853                      AOP(result)->aopu.aop_dir,
10854                      AOP(result)->aopu.aop_dir);
10855       goto release ;
10856     }
10857
10858     /* we need to or */
10859     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10860     pic16_toBoolean(right);
10861     emitSKPZ;
10862     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10863     //pic16_aopPut(AOP(result),"a",0);
10864     goto release ;
10865   }
10866
10867   /* bit variables done */
10868   /* general case */
10869   size = AOP_SIZE(result);
10870   offset = 0 ;
10871
10872   if(AOP_TYPE(right) == AOP_LIT) {
10873         if(!IS_FLOAT(operandType( right )))
10874                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10875         else {
10876            union {
10877               unsigned long lit_int;
10878               float lit_float;
10879             } info;
10880         
10881                 /* take care if literal is a float */
10882                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
10883                 lit = info.lit_int;
10884         }
10885   }
10886
10887 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
10888 //                      sizeof(unsigned long int), sizeof(float));
10889
10890   if(AOP_TYPE(right) != AOP_LIT
10891         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
10892         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
10893         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
10894
10895         // set up table pointer
10896         if( (AOP_TYPE(right) == AOP_PCODE)
10897                 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
10898                 || (AOP(right)->aopu.pcop->type == PO_DIR)))
10899         {
10900                 fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
10901                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
10902                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10903                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
10904                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10905                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
10906                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10907         } else {
10908                 fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
10909                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
10910                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
10911                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
10912                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
10913                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
10914                                 pic16_popCopyReg(&pic16_pc_tblptru)));
10915         }
10916
10917         size = min(AOP_SIZE(right), AOP_SIZE(result));
10918         while(size--) {
10919                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10920                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
10921                         pic16_popGet(AOP(result),offset)));
10922                 offset++;
10923         }
10924
10925         if(AOP_SIZE(result) > AOP_SIZE(right)) {
10926                 size = AOP_SIZE(result) - AOP_SIZE(right);
10927                 while(size--) {
10928                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
10929                         offset++;
10930                 }
10931         }
10932         goto release;
10933   }
10934
10935
10936
10937 #if 0
10938 /* VR - What is this?! */
10939   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10940     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10941     if(aopIdx(AOP(result),0) == 4) {
10942
10943       /* this is a workaround to save value of right into wreg too,
10944        * value of wreg is going to be used later */
10945       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10946       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10947       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10948       goto release;
10949     } else
10950 //      assert(0);
10951       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10952   }
10953 #endif
10954
10955   know_W=-1;
10956   while (size--) {
10957   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10958     if(AOP_TYPE(right) == AOP_LIT) {
10959       if(lit&0xff) {
10960         if(know_W != (lit&0xff))
10961           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10962         know_W = lit&0xff;
10963         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10964       } else
10965         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10966
10967       lit >>= 8;
10968
10969     } else if (AOP_TYPE(right) == AOP_CRY) {
10970       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10971       if(offset == 0) {
10972         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10973         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10974       }
10975     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10976         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10977         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10978     } else {
10979   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10980
10981 #if 1
10982         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10983            normally should work, but mind that the W register live range
10984            is not checked, so if the code generator assumes that the W
10985            is already loaded after such a pair, wrong code will be generated.
10986            
10987            Checking the live range is the next step.
10988            This is experimental code yet and has not been fully tested yet.
10989            USE WITH CARE. Revert to old code by setting 0 to the condition above.
10990            Vangelis Rokas 030603 (vrokas@otenet.gr) */
10991            
10992         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10993 #else   
10994         /* This is the old code, which is assumed(?!) that works fine(!?) */
10995
10996         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10997         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10998 #endif
10999     }
11000             
11001     offset++;
11002   }
11003
11004     
11005  release:
11006   pic16_freeAsmop (right,NULL,ic,FALSE);
11007   pic16_freeAsmop (result,NULL,ic,TRUE);
11008 }   
11009
11010 /*-----------------------------------------------------------------*/
11011 /* genJumpTab - generates code for jump table                       */
11012 /*-----------------------------------------------------------------*/
11013 static void genJumpTab (iCode *ic)
11014 {
11015     symbol *jtab;
11016     char *l;
11017
11018     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11019
11020     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
11021     /* get the condition into accumulator */
11022     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
11023     MOVA(l);
11024     /* multiply by three */
11025     pic16_emitcode("add","a,acc");
11026     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
11027
11028     jtab = newiTempLabel(NULL);
11029     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
11030     pic16_emitcode("jmp","@a+dptr");
11031     pic16_emitcode("","%05d_DS_:",jtab->key+100);
11032
11033     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
11034     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
11035     emitSKPNC;
11036     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
11037     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
11038     pic16_emitpLabel(jtab->key);
11039
11040     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
11041
11042     /* now generate the jump labels */
11043     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
11044          jtab = setNextItem(IC_JTLABELS(ic))) {
11045         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
11046         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
11047         
11048     }
11049
11050 }
11051
11052 /*-----------------------------------------------------------------*/
11053 /* genMixedOperation - gen code for operators between mixed types  */
11054 /*-----------------------------------------------------------------*/
11055 /*
11056   TSD - Written for the PIC port - but this unfortunately is buggy.
11057   This routine is good in that it is able to efficiently promote 
11058   types to different (larger) sizes. Unfortunately, the temporary
11059   variables that are optimized out by this routine are sometimes
11060   used in other places. So until I know how to really parse the 
11061   iCode tree, I'm going to not be using this routine :(.
11062 */
11063 static int genMixedOperation (iCode *ic)
11064 {
11065 #if 0
11066   operand *result = IC_RESULT(ic);
11067   sym_link *ctype = operandType(IC_LEFT(ic));
11068   operand *right = IC_RIGHT(ic);
11069   int ret = 0;
11070   int big,small;
11071   int offset;
11072
11073   iCode *nextic;
11074   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
11075
11076   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11077
11078   nextic = ic->next;
11079   if(!nextic)
11080     return 0;
11081
11082   nextright = IC_RIGHT(nextic);
11083   nextleft  = IC_LEFT(nextic);
11084   nextresult = IC_RESULT(nextic);
11085
11086   pic16_aopOp(right,ic,FALSE);
11087   pic16_aopOp(result,ic,FALSE);
11088   pic16_aopOp(nextright,  nextic, FALSE);
11089   pic16_aopOp(nextleft,   nextic, FALSE);
11090   pic16_aopOp(nextresult, nextic, FALSE);
11091
11092   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
11093
11094     operand *t = right;
11095     right = nextright;
11096     nextright = t; 
11097
11098     pic16_emitcode(";remove right +","");
11099
11100   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
11101 /*
11102     operand *t = right;
11103     right = nextleft;
11104     nextleft = t; 
11105 */
11106     pic16_emitcode(";remove left +","");
11107   } else
11108     return 0;
11109
11110   big = AOP_SIZE(nextleft);
11111   small = AOP_SIZE(nextright);
11112
11113   switch(nextic->op) {
11114
11115   case '+':
11116     pic16_emitcode(";optimize a +","");
11117     /* if unsigned or not an integral type */
11118     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
11119       pic16_emitcode(";add a bit to something","");
11120     } else {
11121
11122       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
11123
11124       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
11125         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
11126         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
11127       } else
11128         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
11129
11130       offset = 0;
11131       while(--big) {
11132
11133         offset++;
11134
11135         if(--small) {
11136           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11137             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11138             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11139           }
11140
11141           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11142           emitSKPNC;
11143           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11144                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
11145                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
11146           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11147           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
11148
11149         } else {
11150           pic16_emitcode("rlf","known_zero,w");
11151
11152           /*
11153             if right is signed
11154               btfsc  right,7
11155                addlw ff
11156           */
11157           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11158             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11159             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11160           } else {
11161             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11162           }
11163         }
11164       }
11165       ret = 1;
11166     }
11167   }
11168   ret = 1;
11169
11170 release:
11171   pic16_freeAsmop(right,NULL,ic,TRUE);
11172   pic16_freeAsmop(result,NULL,ic,TRUE);
11173   pic16_freeAsmop(nextright,NULL,ic,TRUE);
11174   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
11175   if(ret)
11176     nextic->generated = 1;
11177
11178   return ret;
11179 #else
11180   return 0;
11181 #endif
11182 }
11183 /*-----------------------------------------------------------------*/
11184 /* genCast - gen code for casting                                  */
11185 /*-----------------------------------------------------------------*/
11186 static void genCast (iCode *ic)
11187 {
11188   operand *result = IC_RESULT(ic);
11189   sym_link *ctype = operandType(IC_LEFT(ic));
11190   sym_link *rtype = operandType(IC_RIGHT(ic));
11191   operand *right = IC_RIGHT(ic);
11192   int size, offset ;
11193
11194         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11195         /* if they are equivalent then do nothing */
11196         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
11197                 return ;
11198
11199         pic16_aopOp(right,ic,FALSE) ;
11200         pic16_aopOp(result,ic,FALSE);
11201
11202         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11203
11204         /* if the result is a bit */
11205         if (AOP_TYPE(result) == AOP_CRY) {
11206         
11207                 /* if the right size is a literal then
11208                  * we know what the value is */
11209                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11210
11211                 if (AOP_TYPE(right) == AOP_LIT) {
11212                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
11213                                 pic16_popGet(AOP(result),0));
11214
11215                         if (((int) operandLitValue(right))) 
11216                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
11217                                         AOP(result)->aopu.aop_dir,
11218                                         AOP(result)->aopu.aop_dir);
11219                         else
11220                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
11221                                         AOP(result)->aopu.aop_dir,
11222                                         AOP(result)->aopu.aop_dir);
11223                         goto release;
11224                 }
11225
11226                 /* the right is also a bit variable */
11227                 if (AOP_TYPE(right) == AOP_CRY) {
11228                         emitCLRC;
11229                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
11230
11231                         pic16_emitcode("clrc","");
11232                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11233                                 AOP(right)->aopu.aop_dir,
11234                                 AOP(right)->aopu.aop_dir);
11235                         pic16_aopPut(AOP(result),"c",0);
11236                         goto release ;
11237                 }
11238
11239                 /* we need to or */
11240                 if (AOP_TYPE(right) == AOP_REG) {
11241                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
11242                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
11243                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
11244                 }
11245                 pic16_toBoolean(right);
11246                 pic16_aopPut(AOP(result),"a",0);
11247                 goto release ;
11248         }
11249
11250         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
11251           int offset = 1;
11252
11253                 size = AOP_SIZE(result);
11254
11255                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11256
11257                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
11258                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
11259                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
11260
11261                 while (size--)
11262                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11263
11264                 goto release;
11265         }
11266
11267         /* if they are the same size : or less */
11268         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
11269
11270                 /* if they are in the same place */
11271                 if (pic16_sameRegs(AOP(right),AOP(result)))
11272                         goto release;
11273
11274                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11275 #if 0
11276                 if (IS_PTR_CONST(rtype))
11277 #else
11278                 if (IS_CODEPTR(rtype))
11279 #endif
11280                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
11281
11282 #if 0
11283                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
11284 #else
11285                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
11286 #endif
11287                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
11288
11289 #if 0
11290                 if(AOP_TYPE(right) == AOP_IMMD) {
11291                   pCodeOp *pcop0, *pcop1, *pcop2;
11292                   symbol *sym = OP_SYMBOL( right );
11293
11294                         size = AOP_SIZE(result);
11295                         /* low */
11296                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11297                         /* high */
11298                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11299                         /* upper */
11300                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11301         
11302                         if (size == 3) {
11303                                 pic16_emitpcode(POC_MOVLW, pcop0);
11304                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11305                                 pic16_emitpcode(POC_MOVLW, pcop1);
11306                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11307                                 pic16_emitpcode(POC_MOVLW, pcop2);
11308                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11309                         } else
11310                         if (size == 2) {
11311                                 pic16_emitpcode(POC_MOVLW, pcop0);
11312                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11313                                 pic16_emitpcode(POC_MOVLW, pcop1);
11314                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11315                         } else {
11316                                 pic16_emitpcode(POC_MOVLW, pcop0);
11317                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11318                         }
11319                 } else
11320 #endif
11321                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11322                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
11323                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11324                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
11325                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11326                         if(AOP_SIZE(result) <2)
11327                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
11328                 } else {
11329                         /* if they in different places then copy */
11330                         size = AOP_SIZE(result);
11331                         offset = 0 ;
11332                         while (size--) {
11333                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11334                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11335                                 offset++;
11336                         }
11337                 }
11338                 goto release;
11339         }
11340
11341         /* if the result is of type pointer */
11342         if (IS_PTR(ctype)) {
11343           int p_type;
11344           sym_link *type = operandType(right);
11345           sym_link *etype = getSpec(type);
11346
11347                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
11348
11349                 /* pointer to generic pointer */
11350                 if (IS_GENPTR(ctype)) {
11351                   char *l = zero;
11352             
11353                         if (IS_PTR(type)) 
11354                                 p_type = DCL_TYPE(type);
11355                         else {
11356                 /* we have to go by the storage class */
11357                 p_type = PTR_TYPE(SPEC_OCLS(etype));
11358
11359 /*              if (SPEC_OCLS(etype)->codesp )  */
11360 /*                  p_type = CPOINTER ;  */
11361 /*              else */
11362 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11363 /*                      p_type = FPOINTER ; */
11364 /*                  else */
11365 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11366 /*                          p_type = PPOINTER; */
11367 /*                      else */
11368 /*                          if (SPEC_OCLS(etype) == idata ) */
11369 /*                              p_type = IPOINTER ; */
11370 /*                          else */
11371 /*                              p_type = POINTER ; */
11372             }
11373                 
11374             /* the first two bytes are known */
11375       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
11376             size = GPTRSIZE - 1; 
11377             offset = 0 ;
11378             while (size--) {
11379               if(offset < AOP_SIZE(right)) {
11380       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
11381                 if ((AOP_TYPE(right) == AOP_PCODE) && 
11382                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11383                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11384                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11385                 } else { 
11386                   pic16_aopPut(AOP(result),
11387                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11388                          offset);
11389                 }
11390               } else 
11391                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11392               offset++;
11393             }
11394             /* the last byte depending on type */
11395             switch (p_type) {
11396             case IPOINTER:
11397             case POINTER:
11398                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11399                 break;
11400             case FPOINTER:
11401               pic16_emitcode(";BUG!? ","%d",__LINE__);
11402                 l = one;
11403                 break;
11404             case CPOINTER:
11405               pic16_emitcode(";BUG!? ","%d",__LINE__);
11406                 l = "#0x02";
11407                 break;                          
11408             case PPOINTER:
11409               pic16_emitcode(";BUG!? ","%d",__LINE__);
11410                 l = "#0x03";
11411                 break;
11412                 
11413             default:
11414                 /* this should never happen */
11415                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11416                        "got unknown pointer type");
11417                 exit(1);
11418             }
11419             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
11420             goto release ;
11421         }
11422         
11423         /* just copy the pointers */
11424         size = AOP_SIZE(result);
11425         offset = 0 ;
11426         while (size--) {
11427             pic16_aopPut(AOP(result),
11428                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11429                    offset);
11430             offset++;
11431         }
11432         goto release ;
11433     }
11434     
11435
11436
11437     /* so we now know that the size of destination is greater
11438     than the size of the source.
11439     Now, if the next iCode is an operator then we might be
11440     able to optimize the operation without performing a cast.
11441     */
11442     if(genMixedOperation(ic))
11443       goto release;
11444
11445     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11446     
11447     /* we move to result for the size of source */
11448     size = AOP_SIZE(right);
11449     offset = 0 ;
11450     while (size--) {
11451       pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
11452 //      pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
11453 //      pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
11454       offset++;
11455     }
11456
11457     /* now depending on the sign of the destination */
11458     size = AOP_SIZE(result) - AOP_SIZE(right);
11459     /* if unsigned or not an integral type */
11460     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11461       while (size--)
11462         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11463     } else {
11464       /* we need to extend the sign :( */
11465
11466       if(size == 1) {
11467         /* Save one instruction of casting char to int */
11468         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
11469         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11470         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
11471       } else {
11472         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11473
11474         if(offset)
11475           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11476         else
11477           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11478         
11479         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
11480
11481         while (size--)
11482           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
11483       }
11484     }
11485
11486 release:
11487     pic16_freeAsmop(right,NULL,ic,TRUE);
11488     pic16_freeAsmop(result,NULL,ic,TRUE);
11489
11490 }
11491
11492 /*-----------------------------------------------------------------*/
11493 /* genDjnz - generate decrement & jump if not zero instrucion      */
11494 /*-----------------------------------------------------------------*/
11495 static int genDjnz (iCode *ic, iCode *ifx)
11496 {
11497     symbol *lbl, *lbl1;
11498     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11499
11500     if (!ifx)
11501         return 0;
11502     
11503     /* if the if condition has a false label
11504        then we cannot save */
11505     if (IC_FALSE(ifx))
11506         return 0;
11507
11508     /* if the minus is not of the form 
11509        a = a - 1 */
11510     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11511         !IS_OP_LITERAL(IC_RIGHT(ic)))
11512         return 0;
11513
11514     if (operandLitValue(IC_RIGHT(ic)) != 1)
11515         return 0;
11516
11517     /* if the size of this greater than one then no
11518        saving */
11519     if (getSize(operandType(IC_RESULT(ic))) > 1)
11520         return 0;
11521
11522     /* otherwise we can save BIG */
11523     lbl = newiTempLabel(NULL);
11524     lbl1= newiTempLabel(NULL);
11525
11526     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11527     
11528     if (IS_AOP_PREG(IC_RESULT(ic))) {
11529         pic16_emitcode("dec","%s",
11530                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11531         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11532         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11533     } else {    
11534
11535
11536       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11537       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11538
11539       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11540       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
11541
11542     }
11543 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11544 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11545 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11546 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11547
11548     
11549     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11550     ifx->generated = 1;
11551     return 1;
11552 }
11553
11554 /*-----------------------------------------------------------------*/
11555 /* genReceive - generate code for a receive iCode                  */
11556 /*-----------------------------------------------------------------*/
11557 static void genReceive (iCode *ic)
11558 {    
11559         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11560
11561 #if 0
11562         fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
11563                 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
11564 #endif
11565 //      pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
11566
11567         if (isOperandInFarSpace(IC_RESULT(ic)) &&
11568                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11569                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11570
11571           int size = getSize(operandType(IC_RESULT(ic)));
11572           int offset =  pic16_fReturnSizePic - size;
11573
11574                 assert( 0 );
11575                 while (size--) {
11576                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11577                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11578                         offset++;
11579                 }
11580
11581                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
11582
11583                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11584                 size = AOP_SIZE(IC_RESULT(ic));
11585                 offset = 0;
11586                 while (size--) {
11587                         pic16_emitcode ("pop","acc");
11588                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11589                 }
11590         } else {
11591                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
11592
11593                 _G.accInUse++;
11594                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11595                 _G.accInUse--;
11596                 assignResultValue(IC_RESULT(ic), 0);
11597         }
11598
11599         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11600 }
11601
11602 /*-----------------------------------------------------------------*/
11603 /* genDummyRead - generate code for dummy read of volatiles        */
11604 /*-----------------------------------------------------------------*/
11605 static void
11606 genDummyRead (iCode * ic)
11607 {
11608   pic16_emitcode ("; genDummyRead","");
11609   pic16_emitcode ("; not implemented","");
11610
11611   ic = ic;
11612 }
11613
11614 /*-----------------------------------------------------------------*/
11615 /* genpic16Code - generate code for pic16 based controllers        */
11616 /*-----------------------------------------------------------------*/
11617 /*
11618  * At this point, ralloc.c has gone through the iCode and attempted
11619  * to optimize in a way suitable for a PIC. Now we've got to generate
11620  * PIC instructions that correspond to the iCode.
11621  *
11622  * Once the instructions are generated, we'll pass through both the
11623  * peep hole optimizer and the pCode optimizer.
11624  *-----------------------------------------------------------------*/
11625
11626 void genpic16Code (iCode *lic)
11627 {
11628     iCode *ic;
11629     int cln = 0;
11630
11631     lineHead = lineCurr = NULL;
11632
11633     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11634     pic16_addpBlock(pb);
11635
11636 #if 0
11637     /* if debug information required */
11638     if (options.debug && currFunc) {
11639       if (currFunc) {
11640         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11641       }
11642     }
11643 #endif
11644
11645     for (ic = lic ; ic ; ic = ic->next ) {
11646
11647       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11648         if ( cln != ic->lineno ) {
11649             if ( options.debug ) {
11650               debugFile->writeCLine (ic);
11651             }
11652             
11653             if(!options.noCcodeInAsm) {
11654                 pic16_addpCode2pBlock(pb,
11655                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
11656                                 printCLine(ic->filename, ic->lineno)));
11657             }
11658
11659             cln = ic->lineno ;
11660         }
11661         
11662         if(options.iCodeInAsm) {
11663                 char *l;
11664                 /* insert here code to print iCode as comment */
11665                 l = Safe_strdup(printILine(ic));
11666                 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11667         }
11668         
11669         /* if the result is marked as
11670            spilt and rematerializable or code for
11671            this has already been generated then
11672            do nothing */
11673         if (resultRemat(ic) || ic->generated ) 
11674             continue ;
11675         
11676         /* depending on the operation */
11677         switch (ic->op) {
11678         case '!' :
11679             pic16_genNot(ic);
11680             break;
11681             
11682         case '~' :
11683             pic16_genCpl(ic);
11684             break;
11685             
11686         case UNARYMINUS:
11687             genUminus (ic);
11688             break;
11689             
11690         case IPUSH:
11691             genIpush (ic);
11692             break;
11693             
11694         case IPOP:
11695             /* IPOP happens only when trying to restore a 
11696                spilt live range, if there is an ifx statement
11697                following this pop then the if statement might
11698                be using some of the registers being popped which
11699                would destroy the contents of the register so
11700                we need to check for this condition and handle it */
11701             if (ic->next            && 
11702                 ic->next->op == IFX &&
11703                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
11704                 genIfx (ic->next,ic);
11705             else
11706                 genIpop (ic);
11707             break; 
11708             
11709         case CALL:
11710             genCall (ic);
11711             break;
11712             
11713         case PCALL:
11714             genPcall (ic);
11715             break;
11716             
11717         case FUNCTION:
11718             genFunction (ic);
11719             break;
11720             
11721         case ENDFUNCTION:
11722             genEndFunction (ic);
11723             break;
11724             
11725         case RETURN:
11726             genRet (ic);
11727             break;
11728             
11729         case LABEL:
11730             genLabel (ic);
11731             break;
11732             
11733         case GOTO:
11734             genGoto (ic);
11735             break;
11736             
11737         case '+' :
11738             pic16_genPlus (ic) ;
11739             break;
11740             
11741         case '-' :
11742             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11743                 pic16_genMinus (ic);
11744             break;
11745             
11746         case '*' :
11747             genMult (ic);
11748             break;
11749             
11750         case '/' :
11751             genDiv (ic) ;
11752             break;
11753             
11754         case '%' :
11755             genMod (ic);
11756             break;
11757             
11758         case '>' :
11759             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
11760             break;
11761             
11762         case '<' :
11763             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11764             break;
11765             
11766         case LE_OP:
11767         case GE_OP:
11768         case NE_OP:
11769             
11770             /* note these two are xlated by algebraic equivalence
11771                during parsing SDCC.y */
11772             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11773                    "got '>=' or '<=' shouldn't have come here");
11774             break;      
11775             
11776         case EQ_OP:
11777             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11778             break;          
11779             
11780         case AND_OP:
11781             genAndOp (ic);
11782             break;
11783             
11784         case OR_OP:
11785             genOrOp (ic);
11786             break;
11787             
11788         case '^' :
11789             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11790             break;
11791             
11792         case '|' :
11793                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11794             break;
11795             
11796         case BITWISEAND:
11797             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11798             break;
11799             
11800         case INLINEASM:
11801             genInline (ic);
11802             break;
11803             
11804         case RRC:
11805             genRRC (ic);
11806             break;
11807             
11808         case RLC:
11809             genRLC (ic);
11810             break;
11811             
11812         case GETHBIT:
11813             genGetHbit (ic);
11814             break;
11815             
11816         case LEFT_OP:
11817             genLeftShift (ic);
11818             break;
11819             
11820         case RIGHT_OP:
11821             genRightShift (ic);
11822             break;
11823             
11824         case GET_VALUE_AT_ADDRESS:
11825             genPointerGet(ic);
11826             break;
11827             
11828         case '=' :
11829             if (POINTER_SET(ic))
11830                 genPointerSet(ic);
11831             else
11832                 genAssign(ic);
11833             break;
11834             
11835         case IFX:
11836             genIfx (ic,NULL);
11837             break;
11838             
11839         case ADDRESS_OF:
11840             genAddrOf (ic);
11841             break;
11842             
11843         case JUMPTABLE:
11844             genJumpTab (ic);
11845             break;
11846             
11847         case CAST:
11848             genCast (ic);
11849             break;
11850             
11851         case RECEIVE:
11852             genReceive(ic);
11853             break;
11854             
11855         case SEND:
11856             addSet(&_G.sendSet,ic);
11857             break;
11858
11859         case DUMMY_READ_VOLATILE:
11860           genDummyRead (ic);
11861           break;
11862
11863         default :
11864             ic = ic;
11865         }
11866     }
11867
11868
11869     /* now we are ready to call the
11870        peep hole optimizer */
11871     if (!options.nopeep) {
11872       peepHole (&lineHead);
11873     }
11874     /* now do the actual printing */
11875     printLine (lineHead,codeOutFile);
11876
11877 #ifdef PCODE_DEBUG
11878     DFPRINTF((stderr,"printing pBlock\n\n"));
11879     pic16_printpBlock(stdout,pb);
11880 #endif
11881
11882     return;
11883 }
11884