* src/SDCCicode.c (piCode): applied patch from Raphael Neider,
[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
1126 #if 0
1127         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1128                             __FUNCTION__,__LINE__,
1129                             sym->usl.spillLoc->rname,
1130                             sym->rname, sym->usl.spillLoc->offset);
1131 #endif
1132
1133         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1134         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1135         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1136                                           getSize(sym->type), 
1137                                           sym->usl.spillLoc->offset, op);
1138         aop->size = getSize(sym->type);
1139
1140         return;
1141     }
1142
1143     {
1144       sym_link *type = operandType(op);
1145 #if 0
1146       if(IS_PTR_CONST(type)) 
1147 #else
1148       if(IS_CODEPTR(type)) 
1149 #endif
1150         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1151     }
1152
1153     /* must be in a register */
1154     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1155     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1156     aop->size = sym->nRegs;
1157     for ( i = 0 ; i < sym->nRegs ;i++)
1158         aop->aopu.aop_reg[i] = sym->regs[i];
1159 }
1160
1161 /*-----------------------------------------------------------------*/
1162 /* pic16_freeAsmop - free up the asmop given to an operand               */
1163 /*----------------------------------------------------------------*/
1164 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1165 {   
1166     asmop *aop ;
1167
1168     if (!op)
1169         aop = aaop;
1170     else 
1171         aop = op->aop;
1172
1173     if (!aop)
1174         return ;
1175
1176     if (aop->freed)
1177         goto dealloc; 
1178
1179     aop->freed = 1;
1180
1181     /* depending on the asmop type only three cases need work AOP_RO
1182        , AOP_R1 && AOP_STK */
1183 #if 1
1184     switch (aop->type) {
1185         case AOP_FSR0 :
1186             if (_G.fsr0Pushed ) {
1187                 if (pop) {
1188                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1189                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1190 //                    pic16_emitcode ("pop","ar0");
1191                     _G.fsr0Pushed--;
1192                 }
1193             }
1194             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1195             break;
1196
1197         case AOP_FSR2 :
1198             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1199             break;
1200
1201         case AOP_R0 :
1202             if (_G.r0Pushed ) {
1203                 if (pop) {
1204                     pic16_emitcode ("pop","ar0");     
1205                     _G.r0Pushed--;
1206                 }
1207             }
1208             bitVectUnSetBit(ic->rUsed,R0_IDX);
1209             break;
1210
1211         case AOP_R1 :
1212             if (_G.r1Pushed ) {
1213                 if (pop) {
1214                     pic16_emitcode ("pop","ar1");
1215                     _G.r1Pushed--;
1216                 }
1217             }
1218             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1219             break;
1220
1221         case AOP_STK :
1222         {
1223             int sz = aop->size;    
1224             int stk = aop->aopu.aop_stk + aop->size;
1225             bitVectUnSetBit(ic->rUsed,R0_IDX);
1226             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1227
1228             getFreePtr(ic,&aop,FALSE);
1229             
1230             if (options.stack10bit)
1231             {
1232                 /* I'm not sure what to do here yet... */
1233                 /* #STUB */
1234                 fprintf(stderr, 
1235                         "*** Warning: probably generating bad code for "
1236                         "10 bit stack mode.\n");
1237             }
1238             
1239             if (stk) {
1240                 pic16_emitcode ("mov","a,_bp");
1241                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1242                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1243             } else {
1244                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1245             }
1246
1247             while (sz--) {
1248                 pic16_emitcode("pop","acc");
1249                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1250                 if (!sz) break;
1251                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1252             }
1253             op->aop = aop;
1254             pic16_freeAsmop(op,NULL,ic,TRUE);
1255             if (_G.r0Pushed) {
1256                 pic16_emitcode("pop","ar0");
1257                 _G.r0Pushed--;
1258             }
1259
1260             if (_G.r1Pushed) {
1261                 pic16_emitcode("pop","ar1");
1262                 _G.r1Pushed--;
1263             }       
1264         }
1265     }
1266 #endif
1267
1268 dealloc:
1269     /* all other cases just dealloc */
1270     if (op ) {
1271         op->aop = NULL;
1272         if (IS_SYMOP(op)) {
1273             OP_SYMBOL(op)->aop = NULL;    
1274             /* if the symbol has a spill */
1275             if (SPIL_LOC(op))
1276                 SPIL_LOC(op)->aop = NULL;
1277         }
1278     }
1279 }
1280
1281 /*-----------------------------------------------------------------*/
1282 /* pic16_aopGet - for fetching value of the aop                          */
1283 /*-----------------------------------------------------------------*/
1284 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1285 {
1286     char *s = buffer ;
1287     char *rs;
1288
1289     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1290
1291     /* offset is greater than size then zero */
1292     if (offset > (aop->size - 1) &&
1293         aop->type != AOP_LIT)
1294         return zero;
1295
1296     /* depending on type */
1297     switch (aop->type) {
1298
1299     case AOP_FSR0:
1300     case AOP_FSR2:
1301       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1302       rs = Safe_calloc(1, strlen(s)+1);
1303       strcpy(rs, s);
1304       return (rs);
1305       
1306 #if 0
1307       /* if we need to increment it */
1308       while (offset > aop->coff)
1309         {
1310           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1311           aop->coff++;
1312         }
1313
1314       while (offset < aop->coff)
1315         {
1316           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1317           aop->coff--;
1318         }
1319       aop->coff = offset;
1320       if (aop->paged)
1321         {
1322           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1323           return (dname ? "acc" : "a");
1324         }
1325       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1326       rs = Safe_calloc (1, strlen (s) + 1);
1327       strcpy (rs, s);
1328       return rs;
1329 #endif
1330
1331         
1332     case AOP_IMMD:
1333         if (bit16) 
1334             sprintf (s,"%s",aop->aopu.aop_immd);
1335         else
1336             if (offset) 
1337                 sprintf(s,"(%s >> %d)",
1338                         aop->aopu.aop_immd,
1339                         offset*8);
1340             else
1341                 sprintf(s,"%s",
1342                         aop->aopu.aop_immd);
1343         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1344         rs = Safe_calloc(1,strlen(s)+1);
1345         strcpy(rs,s);   
1346         return rs;
1347         
1348     case AOP_DIR:
1349       if (offset) {
1350         sprintf(s,"(%s + %d)",
1351                 aop->aopu.aop_dir,
1352                 offset);
1353         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1354       } else
1355             sprintf(s,"%s",aop->aopu.aop_dir);
1356         rs = Safe_calloc(1,strlen(s)+1);
1357         strcpy(rs,s);   
1358         return rs;
1359         
1360     case AOP_REG:
1361       //if (dname) 
1362       //    return aop->aopu.aop_reg[offset]->dname;
1363       //else
1364             return aop->aopu.aop_reg[offset]->name;
1365         
1366     case AOP_CRY:
1367       //pic16_emitcode(";","%d",__LINE__);
1368       return aop->aopu.aop_dir;
1369         
1370     case AOP_ACC:
1371         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1372 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1373 //        assert( 0 );
1374 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1375         rs = Safe_strdup("WREG");
1376         return (rs);
1377
1378     case AOP_LIT:
1379         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1380         rs = Safe_calloc(1,strlen(s)+1);
1381         strcpy(rs,s);   
1382         return rs;
1383         
1384     case AOP_STR:
1385         aop->coff = offset ;
1386         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1387             dname)
1388             return "acc";
1389         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1390         
1391         return aop->aopu.aop_str[offset];
1392         
1393     case AOP_PCODE:
1394       {
1395         pCodeOp *pcop = aop->aopu.pcop;
1396         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1397         if(pcop->name) {
1398           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1399           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1400           sprintf(s,"%s", pcop->name);
1401         } else
1402           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1403
1404       }
1405       rs = Safe_calloc(1,strlen(s)+1);
1406       strcpy(rs,s);   
1407       return rs;
1408
1409       case AOP_STK:
1410 //        pCodeOp *pcop = aop->aop
1411         break;
1412
1413     }
1414
1415     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1416     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1417            "aopget got unsupported aop->type");
1418     exit(0);
1419 }
1420
1421
1422 /*-----------------------------------------------------------------*/
1423 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1424 /*-----------------------------------------------------------------*/
1425 pCodeOp *pic16_popGetTempReg(void)
1426 {
1427   pCodeOp *pcop;
1428   symbol *cfunc;
1429
1430 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1431
1432         cfunc = currFunc;
1433         currFunc = NULL;
1434
1435         pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1436         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1437                 PCOR(pcop)->r->wasUsed=1;
1438                 PCOR(pcop)->r->isFree=0;
1439
1440                 /* push value on stack */
1441                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1442         }
1443
1444         currFunc = cfunc;
1445
1446   return pcop;
1447 }
1448
1449 /*-----------------------------------------------------------------*/
1450 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1451 /*-----------------------------------------------------------------*/
1452 void pic16_popReleaseTempReg(pCodeOp *pcop)
1453 {
1454         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1455
1456         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1457                 PCOR(pcop)->r->isFree = 1;
1458                 
1459                 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1460         }
1461 }
1462 /*-----------------------------------------------------------------*/
1463 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1464 /*-----------------------------------------------------------------*/
1465 pCodeOp *pic16_popGetLabel(unsigned int key)
1466 {
1467
1468   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1469
1470   if(key>max_key)
1471     max_key = key;
1472
1473   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1474 }
1475
1476 /*-----------------------------------------------------------------*/
1477 /* pic16_popCopyReg - copy a pcode operator                              */
1478 /*-----------------------------------------------------------------*/
1479 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1480 {
1481   pCodeOpReg *pcor;
1482
1483   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1484   pcor->pcop.type = pc->pcop.type;
1485   if(pc->pcop.name) {
1486     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1487       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1488   } else
1489     pcor->pcop.name = NULL;
1490
1491   pcor->r = pc->r;
1492   pcor->rIdx = pc->rIdx;
1493   pcor->r->wasUsed=1;
1494
1495 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1496
1497   return PCOP(pcor);
1498 }
1499
1500 /*-----------------------------------------------------------------*/
1501 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1502 /*-----------------------------------------------------------------*/
1503 pCodeOp *pic16_popGetLit(unsigned int lit)
1504 {
1505   return pic16_newpCodeOpLit(lit);
1506 }
1507
1508 /*-----------------------------------------------------------------*/
1509 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1510 /*-----------------------------------------------------------------*/
1511 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1512 {
1513   return pic16_newpCodeOpLit2(lit, arg2);
1514 }
1515
1516
1517 /*-----------------------------------------------------------------*/
1518 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1519 /*-----------------------------------------------------------------*/
1520 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1521 {
1522   return pic16_newpCodeOpImmd(name, offset,index, 0);
1523 }
1524
1525
1526 /*-----------------------------------------------------------------*/
1527 /* pic16_popGet - asm operator to pcode operator conversion              */
1528 /*-----------------------------------------------------------------*/
1529 pCodeOp *pic16_popGetWithString(char *str)
1530 {
1531   pCodeOp *pcop;
1532
1533
1534   if(!str) {
1535     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1536     exit (1);
1537   }
1538
1539   pcop = pic16_newpCodeOp(str,PO_STR);
1540
1541   return pcop;
1542 }
1543
1544 /*-----------------------------------------------------------------*/
1545 /* pic16_popRegFromString -                                        */
1546 /*-----------------------------------------------------------------*/
1547 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1548 {
1549
1550   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1551   pcop->type = PO_DIR;
1552
1553   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1554   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1555
1556   if(!str)
1557     str = "BAD_STRING";
1558
1559   pcop->name = Safe_calloc(1,strlen(str)+1);
1560   strcpy(pcop->name,str);
1561
1562   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1563
1564   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1565   if(PCOR(pcop)->r == NULL) {
1566 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1567 //              __FUNCTION__, __LINE__, str, size, offset);
1568
1569
1570 //    PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1571         fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1572
1573 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1574   } else {
1575 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d",__LINE__,pcop->name,size,offset);
1576   }
1577   PCOR(pcop)->instance = offset;
1578
1579   return pcop;
1580 }
1581
1582 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1583 {
1584   pCodeOp *pcop;
1585
1586 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1587
1588         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1589         PCOR(pcop)->rIdx = rIdx;
1590         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1591
1592         PCOR(pcop)->r->isFree = 0;
1593         PCOR(pcop)->r->wasUsed = 1;
1594
1595         pcop->type = PCOR(pcop)->r->pc_type;
1596
1597   return pcop;
1598 }
1599
1600 /*---------------------------------------------------------------------------------*/
1601 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1602 /*                 VR 030601                                                       */
1603 /*---------------------------------------------------------------------------------*/
1604 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1605 {
1606   pCodeOpReg2 *pcop2;
1607   pCodeOp *temp;
1608   
1609         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1610
1611         /* comment the following check, so errors to throw up */
1612 //      if(!pcop2)return NULL;
1613
1614         temp = pic16_popGet(aop_dst, offset);
1615         pcop2->pcop2 = temp;
1616         
1617   return PCOP(pcop2);
1618 }
1619
1620
1621
1622 /*--------------------------------------------------------------------------------.-*/
1623 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1624 /*                  VR 030601 , adapted by Hans Dorn                                */
1625 /*--------------------------------------------------------------------------------.-*/
1626 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1627 {
1628   pCodeOpReg2 *pcop2;
1629  
1630         pcop2 = (pCodeOpReg2 *)src;
1631         pcop2->pcop2 = dst;
1632         
1633         return PCOP(pcop2);
1634 }
1635
1636
1637
1638 /*---------------------------------------------------------------------------------*/
1639 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1640 /*                     movff instruction                                           */
1641 /*---------------------------------------------------------------------------------*/
1642 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1643 {
1644   pCodeOpReg2 *pcop2;
1645
1646         if(!noalloc) {
1647                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1648                 pcop2->pcop2 = pic16_popCopyReg(dst);
1649         } else {
1650                 /* the pCodeOp may be already allocated */
1651                 pcop2 = (pCodeOpReg2 *)(src);
1652                 pcop2->pcop2 = (pCodeOp *)(dst);
1653         }
1654
1655   return PCOP(pcop2);
1656 }
1657
1658
1659 /*-----------------------------------------------------------------*/
1660 /* pic16_popGet - asm operator to pcode operator conversion              */
1661 /*-----------------------------------------------------------------*/
1662 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1663 {
1664   //char *s = buffer ;
1665   char *rs;
1666   pCodeOp *pcop;
1667
1668     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1669     /* offset is greater than
1670     size then zero */
1671
1672 //    if (offset > (aop->size - 1) &&
1673 //        aop->type != AOP_LIT)
1674 //      return NULL;  //zero;
1675
1676     /* depending on type */
1677     switch (aop->type) {
1678         
1679     case AOP_R0:
1680     case AOP_R1:
1681     case AOP_DPTR:
1682     case AOP_DPTR2:
1683         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1684         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1685         assert( 0 );
1686         return NULL;
1687
1688
1689     case AOP_FSR0:
1690     case AOP_FSR2:
1691       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1692       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
1693       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1694       PCOR(pcop)->r->wasUsed = 1;
1695       PCOR(pcop)->r->isFree = 0;
1696       
1697       PCOR(pcop)->instance = offset;
1698       pcop->type = PCOR(pcop)->r->pc_type;
1699       return (pcop);
1700
1701     case AOP_IMMD:
1702       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1703       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1704
1705     case AOP_ACC:
1706       {
1707         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1708
1709         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1710
1711         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1712         
1713         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1714         PCOR(pcop)->rIdx = rIdx;
1715         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1716         PCOR(pcop)->r->wasUsed=1;
1717         PCOR(pcop)->r->isFree=0;
1718
1719         PCOR(pcop)->instance = offset;
1720         pcop->type = PCOR(pcop)->r->pc_type;
1721 //      rs = aop->aopu.aop_reg[offset]->name;
1722 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1723         return pcop;
1724
1725
1726 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1727 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1728
1729 //      assert( 0 );
1730       }
1731         
1732     case AOP_DIR:
1733       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1734       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1735         
1736     case AOP_REG:
1737       {
1738         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1739
1740         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1741         
1742         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1743 //      pcop->type = PO_GPR_REGISTER;
1744         PCOR(pcop)->rIdx = rIdx;
1745         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
1746         PCOR(pcop)->r->wasUsed=1;
1747         PCOR(pcop)->r->isFree=0;
1748
1749         PCOR(pcop)->instance = offset;
1750         pcop->type = PCOR(pcop)->r->pc_type;
1751         rs = aop->aopu.aop_reg[offset]->name;
1752         DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1753         return pcop;
1754       }
1755
1756     case AOP_CRY:
1757         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1758
1759       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1760       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1761       //if(PCOR(pcop)->r == NULL)
1762       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1763       return pcop;
1764         
1765     case AOP_LIT:
1766         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1767       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1768
1769     case AOP_STR:
1770       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1771       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1772
1773       /*
1774       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1775       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1776       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1777       pcop->type = PCOR(pcop)->r->pc_type;
1778       pcop->name = PCOR(pcop)->r->name;
1779
1780       return pcop;
1781       */
1782
1783     case AOP_PCODE:
1784       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1785                           __LINE__, 
1786                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1787       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1788 #if 1
1789         switch( aop->aopu.pcop->type ) {
1790                 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1791                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1792                 default:
1793                         assert( 0 );    /* should never reach here */;
1794         }
1795 #else
1796       PCOI(pcop)->offset = offset;
1797 #endif
1798       return pcop;
1799     }
1800
1801     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1802            "pic16_popGet got unsupported aop->type");
1803     exit(0);
1804 }
1805 /*-----------------------------------------------------------------*/
1806 /* pic16_aopPut - puts a string for a aop                                */
1807 /*-----------------------------------------------------------------*/
1808 void pic16_aopPut (asmop *aop, char *s, int offset)
1809 {
1810     char *d = buffer ;
1811     symbol *lbl ;
1812
1813     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1814
1815     if (aop->size && offset > ( aop->size - 1)) {
1816         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1817                "pic16_aopPut got offset > aop->size");
1818         exit(0);
1819     }
1820
1821     /* will assign value to value */
1822     /* depending on where it is ofcourse */
1823     switch (aop->type) {
1824     case AOP_DIR:
1825       if (offset) {
1826         sprintf(d,"(%s + %d)",
1827                 aop->aopu.aop_dir,offset);
1828         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1829
1830       } else
1831             sprintf(d,"%s",aop->aopu.aop_dir);
1832         
1833         if (strcmp(d,s)) {
1834           DEBUGpic16_emitcode(";","%d",__LINE__);
1835           if(strcmp(s,"W"))
1836             pic16_emitcode("movf","%s,w",s);
1837           pic16_emitcode("movwf","%s",d);
1838
1839           if(strcmp(s,"W")) {
1840             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1841             if(offset >= aop->size) {
1842               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1843               break;
1844             } else
1845               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1846           }
1847
1848           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1849
1850
1851         }
1852         break;
1853         
1854     case AOP_REG:
1855       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1856         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1857           /*
1858             if (*s == '@'           ||
1859                 strcmp(s,"r0") == 0 ||
1860                 strcmp(s,"r1") == 0 ||
1861                 strcmp(s,"r2") == 0 ||
1862                 strcmp(s,"r3") == 0 ||
1863                 strcmp(s,"r4") == 0 ||
1864                 strcmp(s,"r5") == 0 ||
1865                 strcmp(s,"r6") == 0 || 
1866                 strcmp(s,"r7") == 0 )
1867                 pic16_emitcode("mov","%s,%s  ; %d",
1868                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1869             else
1870           */
1871
1872           if(strcmp(s,"W")==0 )
1873             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1874
1875           pic16_emitcode("movwf","%s",
1876                    aop->aopu.aop_reg[offset]->name);
1877
1878           if(strcmp(s,zero)==0) {
1879             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1880
1881           } else if(strcmp(s,"W")==0) {
1882             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1883             pcop->type = PO_GPR_REGISTER;
1884
1885             PCOR(pcop)->rIdx = -1;
1886             PCOR(pcop)->r = NULL;
1887
1888             DEBUGpic16_emitcode(";","%d",__LINE__);
1889             pcop->name = Safe_strdup(s);
1890             pic16_emitpcode(POC_MOVFW,pcop);
1891             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1892           } else if(strcmp(s,one)==0) {
1893             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1894             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1895           } else {
1896             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1897           }
1898         }
1899         break;
1900         
1901     case AOP_DPTR:
1902     case AOP_DPTR2:
1903     
1904     if (aop->type == AOP_DPTR2)
1905     {
1906         genSetDPTR(1);
1907     }
1908     
1909         if (aop->code) {
1910             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1911                    "pic16_aopPut writting to code space");
1912             exit(0);
1913         }
1914         
1915         while (offset > aop->coff) {
1916             aop->coff++;
1917             pic16_emitcode ("inc","dptr");
1918         }
1919         
1920         while (offset < aop->coff) {
1921             aop->coff-- ;
1922             pic16_emitcode("lcall","__decdptr");
1923         }
1924         
1925         aop->coff = offset;
1926         
1927         /* if not in accumulater */
1928         MOVA(s);        
1929         
1930         pic16_emitcode ("movx","@dptr,a");
1931         
1932     if (aop->type == AOP_DPTR2)
1933     {
1934         genSetDPTR(0);
1935     }
1936         break;
1937         
1938     case AOP_R0:
1939     case AOP_R1:
1940         while (offset > aop->coff) {
1941             aop->coff++;
1942             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1943         }
1944         while (offset < aop->coff) {
1945             aop->coff-- ;
1946             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1947         }
1948         aop->coff = offset;
1949         
1950         if (aop->paged) {
1951             MOVA(s);           
1952             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1953             
1954         } else
1955             if (*s == '@') {
1956                 MOVA(s);
1957                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1958             } else
1959                 if (strcmp(s,"r0") == 0 ||
1960                     strcmp(s,"r1") == 0 ||
1961                     strcmp(s,"r2") == 0 ||
1962                     strcmp(s,"r3") == 0 ||
1963                     strcmp(s,"r4") == 0 ||
1964                     strcmp(s,"r5") == 0 ||
1965                     strcmp(s,"r6") == 0 || 
1966                     strcmp(s,"r7") == 0 ) {
1967                     char buffer[10];
1968                     sprintf(buffer,"a%s",s);
1969                     pic16_emitcode("mov","@%s,%s",
1970                              aop->aopu.aop_ptr->name,buffer);
1971                 } else
1972                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1973         
1974         break;
1975         
1976     case AOP_STK:
1977         if (strcmp(s,"a") == 0)
1978             pic16_emitcode("push","acc");
1979         else
1980             pic16_emitcode("push","%s",s);
1981         
1982         break;
1983         
1984     case AOP_CRY:
1985         /* if bit variable */
1986         if (!aop->aopu.aop_dir) {
1987             pic16_emitcode("clr","a");
1988             pic16_emitcode("rlc","a");
1989         } else {
1990             if (s == zero) 
1991                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1992             else
1993                 if (s == one)
1994                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1995                 else
1996                     if (!strcmp(s,"c"))
1997                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1998                     else {
1999                         lbl = newiTempLabel(NULL);
2000                         
2001                         if (strcmp(s,"a")) {
2002                             MOVA(s);
2003                         }
2004                         pic16_emitcode("clr","c");
2005                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2006                         pic16_emitcode("cpl","c");
2007                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2008                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2009                     }
2010         }
2011         break;
2012         
2013     case AOP_STR:
2014         aop->coff = offset;
2015         if (strcmp(aop->aopu.aop_str[offset],s))
2016             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2017         break;
2018         
2019     case AOP_ACC:
2020         aop->coff = offset;
2021         if (!offset && (strcmp(s,"acc") == 0))
2022             break;
2023         
2024         if (strcmp(aop->aopu.aop_str[offset],s))
2025             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2026         break;
2027
2028     default :
2029         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2030                "pic16_aopPut got unsupported aop->type");
2031         exit(0);    
2032     }    
2033
2034 }
2035
2036 /*-----------------------------------------------------------------*/
2037 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
2038 /*-----------------------------------------------------------------*/
2039 static void mov2w (asmop *aop, int offset)
2040 {
2041
2042 //  if(!aop)
2043 //    return;
2044
2045         DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2046
2047         if(is_LitAOp(aop))
2048                 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2049         else
2050                 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2051
2052 }
2053
2054
2055 /* push pcop into stack */
2056 void pic16_pushpCodeOp(pCodeOp *pcop)
2057 {
2058 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2059         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
2060 }
2061
2062 /* pop pcop from stack */
2063 void pic16_poppCodeOp(pCodeOp *pcop)
2064 {
2065         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
2066 }
2067
2068
2069 /*-----------------------------------------------------------------*/
2070 /* pushw - pushes wreg to stack                                    */
2071 /*-----------------------------------------------------------------*/
2072 void pushw(void)
2073 {
2074         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2075         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2076 }
2077
2078                 
2079 /*-----------------------------------------------------------------*/
2080 /* pushaop - pushes aop to stack                                   */
2081 /*-----------------------------------------------------------------*/
2082 void pushaop(asmop *aop, int offset)
2083 {
2084         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2085         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
2086 }
2087
2088 /*-----------------------------------------------------------------*/
2089 /* popaop - pops aop from stack                                    */
2090 /*-----------------------------------------------------------------*/
2091 void popaop(asmop *aop, int offset)
2092 {
2093         DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2094         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
2095 }
2096
2097 void popaopidx(asmop *aop, int offset, int index)
2098 {
2099   int ofs=1;
2100
2101         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2102
2103         if(STACK_MODEL_LARGE)ofs++;
2104
2105         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2106         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
2107 }
2108
2109 /*-----------------------------------------------------------------*/
2110 /* reAdjustPreg - points a register back to where it should        */
2111 /*-----------------------------------------------------------------*/
2112 static void reAdjustPreg (asmop *aop)
2113 {
2114     int size ;
2115
2116     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2117     aop->coff = 0;
2118     if ((size = aop->size) <= 1)
2119         return ;
2120     size-- ;
2121     switch (aop->type) {
2122         case AOP_R0 :
2123         case AOP_R1 :
2124             while (size--)
2125                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2126             break;          
2127         case AOP_DPTR :
2128         case AOP_DPTR2:
2129             if (aop->type == AOP_DPTR2)
2130             {
2131                 genSetDPTR(1);
2132             } 
2133             while (size--)
2134             {
2135                 pic16_emitcode("lcall","__decdptr");
2136             }
2137                 
2138             if (aop->type == AOP_DPTR2)
2139             {
2140                 genSetDPTR(0);
2141             }                
2142             break;  
2143
2144     }   
2145
2146 }
2147
2148
2149 #if 0
2150 /*-----------------------------------------------------------------*/
2151 /* opIsGptr: returns non-zero if the passed operand is             */   
2152 /* a generic pointer type.                                         */
2153 /*-----------------------------------------------------------------*/ 
2154 static int opIsGptr(operand *op)
2155 {
2156     sym_link *type = operandType(op);
2157     
2158     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2159     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2160     {
2161         return 1;
2162     }
2163     return 0;        
2164 }
2165 #endif
2166
2167 /*-----------------------------------------------------------------*/
2168 /* pic16_getDataSize - get the operand data size                         */
2169 /*-----------------------------------------------------------------*/
2170 int pic16_getDataSize(operand *op)
2171 {
2172     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2173
2174
2175     return AOP_SIZE(op);
2176
2177     // tsd- in the pic port, the genptr size is 1, so this code here
2178     // fails. ( in the 8051 port, the size was 4).
2179 #if 0
2180     int size;
2181     size = AOP_SIZE(op);
2182     if (size == GPTRSIZE)
2183     {
2184         sym_link *type = operandType(op);
2185         if (IS_GENPTR(type))
2186         {
2187             /* generic pointer; arithmetic operations
2188              * should ignore the high byte (pointer type).
2189              */
2190             size--;
2191     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2192         }
2193     }
2194     return size;
2195 #endif
2196 }
2197
2198 /*-----------------------------------------------------------------*/
2199 /* pic16_outAcc - output Acc                                             */
2200 /*-----------------------------------------------------------------*/
2201 void pic16_outAcc(operand *result)
2202 {
2203   int size,offset;
2204   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2205   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2206
2207
2208   size = pic16_getDataSize(result);
2209   if(size){
2210     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2211     size--;
2212     offset = 1;
2213     /* unsigned or positive */
2214     while(size--)
2215       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2216   }
2217
2218 }
2219
2220 /*-----------------------------------------------------------------*/
2221 /* pic16_outBitC - output a bit C                                  */
2222 /*                 Move to result the value of Carry flag -- VR    */
2223 /*-----------------------------------------------------------------*/
2224 void pic16_outBitC(operand *result)
2225 {
2226   int i;
2227
2228     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2229     /* if the result is bit */
2230     if (AOP_TYPE(result) == AOP_CRY) {
2231         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2232         pic16_aopPut(AOP(result),"c",0);
2233     } else {
2234
2235         i = AOP_SIZE(result);
2236         while(i--) {
2237                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2238         }
2239         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2240         
2241 /*
2242         pic16_emitcode("clr","a  ; %d", __LINE__);
2243         pic16_emitcode("rlc","a");
2244         pic16_outAcc(result);
2245 */
2246     }
2247 }
2248
2249 /*-----------------------------------------------------------------*/
2250 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2251 /*-----------------------------------------------------------------*/
2252 void pic16_toBoolean(operand *oper)
2253 {
2254     int size = AOP_SIZE(oper) - 1;
2255     int offset = 1;
2256
2257     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2258
2259     if ( AOP_TYPE(oper) != AOP_ACC) {
2260       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2261     }
2262     while (size--) {
2263       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2264     }
2265 }
2266
2267
2268 #if !defined(GEN_Not)
2269 /*-----------------------------------------------------------------*/
2270 /* genNot - generate code for ! operation                          */
2271 /*-----------------------------------------------------------------*/
2272 static void pic16_genNot (iCode *ic)
2273 {
2274   symbol *tlbl;
2275   int size;
2276
2277   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2278   /* assign asmOps to operand & result */
2279   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2280   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2281
2282   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2283   /* if in bit space then a special case */
2284   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2285     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2286       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2287       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2288     } else {
2289       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2290       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2291       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2292     }
2293     goto release;
2294   }
2295
2296   size = AOP_SIZE(IC_LEFT(ic));
2297   if(size == 1) {
2298     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2299     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2300     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2301     goto release;
2302   }
2303   pic16_toBoolean(IC_LEFT(ic));
2304
2305   tlbl = newiTempLabel(NULL);
2306   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2307   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2308   pic16_outBitC(IC_RESULT(ic));
2309
2310  release:    
2311   /* release the aops */
2312   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2313   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2314 }
2315 #endif
2316
2317
2318 #if !defined(GEN_Cpl)
2319 /*-----------------------------------------------------------------*/
2320 /* genCpl - generate code for complement                           */
2321 /*-----------------------------------------------------------------*/
2322 static void pic16_genCpl (iCode *ic)
2323 {
2324     int offset = 0;
2325     int size ;
2326
2327
2328     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2329     /* assign asmOps to operand & result */
2330     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2331     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2332
2333     /* if both are in bit space then 
2334     a special case */
2335     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2336         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2337
2338         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2339         pic16_emitcode("cpl","c"); 
2340         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2341         goto release; 
2342     } 
2343
2344     size = AOP_SIZE(IC_RESULT(ic));
2345     while (size--) {
2346 /*
2347         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2348         MOVA(l);       
2349         pic16_emitcode("cpl","a");
2350         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2351 */
2352         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2353               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2354         } else {
2355                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2356                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2357         }
2358         offset++;
2359
2360     }
2361
2362
2363 release:
2364     /* release the aops */
2365     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2366     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2367 }
2368 #endif
2369
2370 /*-----------------------------------------------------------------*/
2371 /* genUminusFloat - unary minus for floating points                */
2372 /*-----------------------------------------------------------------*/
2373 static void genUminusFloat(operand *op,operand *result)
2374 {
2375     int size ,offset =0 ;
2376     char *l;
2377
2378     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2379     /* for this we just need to flip the 
2380     first it then copy the rest in place */
2381     size = AOP_SIZE(op) - 1;
2382     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2383
2384     MOVA(l);    
2385
2386     pic16_emitcode("cpl","acc.7");
2387     pic16_aopPut(AOP(result),"a",3);    
2388
2389     while(size--) {
2390         pic16_aopPut(AOP(result),
2391                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2392                offset);
2393         offset++;
2394     }          
2395 }
2396
2397 /*-----------------------------------------------------------------*/
2398 /* genUminus - unary minus code generation                         */
2399 /*-----------------------------------------------------------------*/
2400 static void genUminus (iCode *ic)
2401 {
2402   int size, i;
2403   sym_link *optype, *rtype;
2404
2405         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2406         
2407         /* assign asmops */
2408         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2409         pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2410
2411         /* if both in bit space then special case */
2412         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2413                 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2414
2415                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2416                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2417                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2418                 
2419                 goto release; 
2420         } 
2421
2422         optype = operandType(IC_LEFT(ic));
2423         rtype = operandType(IC_RESULT(ic));
2424
2425         /* if float then do float stuff */
2426         if (IS_FLOAT(optype)) {
2427                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2428                 goto release;
2429         }
2430
2431         /* otherwise subtract from zero by taking the 2's complement */
2432         size = AOP_SIZE(IC_LEFT(ic));
2433
2434         for(i=0; i<size; i++) {
2435                 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2436                         pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2437                 else {
2438                         pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2439                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2440                 }
2441         }
2442
2443         pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2444         for(i=1; i<size; i++) {
2445                 emitSKPNZ;
2446                 pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2447         }
2448
2449 release:
2450         /* release the aops */
2451         pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2452         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2453 }
2454
2455 /*-----------------------------------------------------------------*/
2456 /* saveRegisters - will look for a call and save the registers     */
2457 /*-----------------------------------------------------------------*/
2458 static void saveRegisters(iCode *lic) 
2459 {
2460     int i;
2461     iCode *ic;
2462     bitVect *rsave;
2463     sym_link *dtype;
2464
2465     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2466     /* look for call */
2467     for (ic = lic ; ic ; ic = ic->next) 
2468         if (ic->op == CALL || ic->op == PCALL)
2469             break;
2470
2471     if (!ic) {
2472         fprintf(stderr,"found parameter push with no function call\n");
2473         return ;
2474     }
2475
2476     /* if the registers have been saved already then
2477     do nothing */
2478     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2479         return ;
2480
2481     /* find the registers in use at this time 
2482     and push them away to safety */
2483     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2484                           ic->rUsed);
2485
2486     ic->regsSaved = 1;
2487     if (options.useXstack) {
2488         if (bitVectBitValue(rsave,R0_IDX))
2489             pic16_emitcode("mov","b,r0");
2490         pic16_emitcode("mov","r0,%s",spname);
2491         for (i = 0 ; i < pic16_nRegs ; i++) {
2492             if (bitVectBitValue(rsave,i)) {
2493                 if (i == R0_IDX)
2494                     pic16_emitcode("mov","a,b");
2495                 else
2496                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2497                 pic16_emitcode("movx","@r0,a");
2498                 pic16_emitcode("inc","r0");
2499             }
2500         }
2501         pic16_emitcode("mov","%s,r0",spname);
2502         if (bitVectBitValue(rsave,R0_IDX))
2503             pic16_emitcode("mov","r0,b");           
2504     }// else
2505     //for (i = 0 ; i < pic16_nRegs ; i++) {
2506     //    if (bitVectBitValue(rsave,i))
2507     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2508     //}
2509
2510     dtype = operandType(IC_LEFT(ic));
2511     if (currFunc && dtype && 
2512         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2513         IFFUNC_ISISR(currFunc->type) &&
2514         !ic->bankSaved) 
2515
2516         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2517
2518 }
2519 /*-----------------------------------------------------------------*/
2520 /* unsaveRegisters - pop the pushed registers                      */
2521 /*-----------------------------------------------------------------*/
2522 static void unsaveRegisters (iCode *ic)
2523 {
2524     int i;
2525     bitVect *rsave;
2526
2527     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2528     /* find the registers in use at this time 
2529     and push them away to safety */
2530     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2531                           ic->rUsed);
2532     
2533     if (options.useXstack) {
2534         pic16_emitcode("mov","r0,%s",spname);   
2535         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2536             if (bitVectBitValue(rsave,i)) {
2537                 pic16_emitcode("dec","r0");
2538                 pic16_emitcode("movx","a,@r0");
2539                 if (i == R0_IDX)
2540                     pic16_emitcode("mov","b,a");
2541                 else
2542                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2543             }       
2544
2545         }
2546         pic16_emitcode("mov","%s,r0",spname);
2547         if (bitVectBitValue(rsave,R0_IDX))
2548             pic16_emitcode("mov","r0,b");
2549     } //else
2550     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2551     //    if (bitVectBitValue(rsave,i))
2552     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2553     //}
2554
2555 }  
2556
2557 #if 0  // patch 14
2558 /*-----------------------------------------------------------------*/
2559 /* pushSide -                                                      */
2560 /*-----------------------------------------------------------------*/
2561 static void pushSide(operand * oper, int size)
2562 {
2563         int offset = 0;
2564     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2565         while (size--) {
2566                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2567                 if (AOP_TYPE(oper) != AOP_REG &&
2568                     AOP_TYPE(oper) != AOP_DIR &&
2569                     strcmp(l,"a") ) {
2570                         pic16_emitcode("mov","a,%s",l);
2571                         pic16_emitcode("push","acc");
2572                 } else
2573                         pic16_emitcode("push","%s",l);
2574         }
2575 }
2576 #endif // patch 14
2577
2578 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2579 {
2580 //              (AOP(left)->aopu.pcop->type == PO_DIR)?
2581
2582         if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2583                 pic16_emitpcode(POC_MOVFW, src);
2584                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2585         } else {
2586                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2587                         src, pic16_popGet(AOP(op), offset)));
2588         }
2589 }
2590
2591
2592 /*-----------------------------------------------------------------*/
2593 /* assignResultValue - assign results to oper, rescall==1 is       */
2594 /*                     called from genCall() or genPCall()         */
2595 /*-----------------------------------------------------------------*/
2596 static void assignResultValue(operand * oper, int rescall)
2597 {
2598   int size = AOP_SIZE(oper);
2599
2600         DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2601         DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2602
2603         if(rescall) {
2604                 /* assign result from a call/pcall function() */
2605                 
2606                 /* function results are stored in a special order,
2607                  * see top of file with Function return policy, or manual */
2608
2609                 if(size <= 4) {
2610                         /* 8-bits, result in WREG */
2611                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2612                         
2613                         if(size>1) {
2614                                 /* 16-bits, result in PRODL:WREG */
2615                                 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2616                         }
2617                         
2618                         if(size>2) {
2619                                 /* 24-bits, result in PRODH:PRODL:WREG */
2620                                 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2621                         }
2622                         
2623                         if(size>3) {
2624                                 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2625                                 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2626                         }
2627                 } else {
2628                         /* >32-bits, result on stack, and FSR0 points to beginning.
2629                          * Fix stack when done */
2630                          /* FIXME FIXME */
2631                         while (size--) {
2632 //                              DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2633 //                              DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2634                 
2635                                 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2636                                 GpsuedoStkPtr++;
2637                         }
2638                         
2639                         /* fix stack */
2640                         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2641                         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2642                         if(STACK_MODEL_LARGE) {
2643                                 emitSKPNC;
2644                                 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2645                         }
2646                 }                       
2647         } else {        
2648                 if(!GpsuedoStkPtr) {
2649 //                      DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2650                         /* The last byte in the assignment is in W */
2651                         size--;
2652                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2653                         GpsuedoStkPtr++;
2654                 }
2655
2656                 while (size--) {
2657 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2658 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2659                 
2660                         popaopidx(AOP(oper), size, GpsuedoStkPtr);
2661                         GpsuedoStkPtr++;
2662
2663 #if 0
2664 #if STACK_SUPPORT
2665                 if(!USE_STACK)
2666                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2667 #else
2668                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2669 #endif
2670 #endif
2671
2672                 }
2673         }
2674                 
2675 }
2676
2677
2678 /*-----------------------------------------------------------------*/
2679 /* genIpush - genrate code for pushing this gets a little complex  */
2680 /*-----------------------------------------------------------------*/
2681 static void genIpush (iCode *ic)
2682 {
2683   int size, offset=0;
2684
2685   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2686
2687
2688         pic16_aopOp(IC_LEFT(ic), ic, FALSE);
2689         
2690
2691         size = AOP_SIZE( IC_LEFT(ic) );
2692         
2693         while(size--) {
2694                 mov2w( AOP(IC_LEFT(ic)), offset );
2695                 pushw();
2696                 offset++;
2697         }
2698         
2699 #if 0
2700     int size, offset = 0 ;
2701     char *l;
2702
2703
2704     /* if this is not a parm push : ie. it is spill push 
2705     and spill push is always done on the local stack */
2706     if (!ic->parmPush) {
2707
2708         /* and the item is spilt then do nothing */
2709         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2710             return ;
2711
2712         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2713         size = AOP_SIZE(IC_LEFT(ic));
2714         /* push it on the stack */
2715         while(size--) {
2716             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2717             if (*l == '#') {
2718                 MOVA(l);
2719                 l = "acc";
2720             }
2721             pic16_emitcode("push","%s",l);
2722         }
2723         return ;        
2724     }
2725
2726     /* this is a paramter push: in this case we call
2727     the routine to find the call and save those
2728     registers that need to be saved */   
2729     saveRegisters(ic);
2730
2731     /* then do the push */
2732     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2733
2734
2735         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2736     size = AOP_SIZE(IC_LEFT(ic));
2737
2738     while (size--) {
2739         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2740         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2741             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2742             strcmp(l,"a") ) {
2743             pic16_emitcode("mov","a,%s",l);
2744             pic16_emitcode("push","acc");
2745         } else
2746             pic16_emitcode("push","%s",l);
2747     }       
2748
2749     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2750 #endif
2751 }
2752
2753 /*-----------------------------------------------------------------*/
2754 /* genIpop - recover the registers: can happen only for spilling   */
2755 /*-----------------------------------------------------------------*/
2756 static void genIpop (iCode *ic)
2757 {
2758   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2759 #if 0
2760     int size,offset ;
2761
2762
2763     /* if the temp was not pushed then */
2764     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2765         return ;
2766
2767     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2768     size = AOP_SIZE(IC_LEFT(ic));
2769     offset = (size-1);
2770     while (size--) 
2771         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2772                                    FALSE,TRUE));
2773
2774     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2775 #endif
2776 }
2777
2778 /*-----------------------------------------------------------------*/
2779 /* unsaverbank - restores the resgister bank from stack            */
2780 /*-----------------------------------------------------------------*/
2781 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2782 {
2783   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2784 #if 0
2785     int i;
2786     asmop *aop ;
2787     regs *r = NULL;
2788
2789     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2790     if (popPsw) {
2791         if (options.useXstack) {
2792             aop = newAsmop(0);
2793             r = getFreePtr(ic,&aop,FALSE);
2794             
2795             
2796             pic16_emitcode("mov","%s,_spx",r->name);
2797             pic16_emitcode("movx","a,@%s",r->name);
2798             pic16_emitcode("mov","psw,a");
2799             pic16_emitcode("dec","%s",r->name);
2800             
2801         }else
2802             pic16_emitcode ("pop","psw");
2803     }
2804
2805     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2806         if (options.useXstack) {       
2807             pic16_emitcode("movx","a,@%s",r->name);
2808             //pic16_emitcode("mov","(%s+%d),a",
2809             //       regspic16[i].base,8*bank+regspic16[i].offset);
2810             pic16_emitcode("dec","%s",r->name);
2811
2812         } else 
2813           pic16_emitcode("pop",""); //"(%s+%d)",
2814         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2815     }
2816
2817     if (options.useXstack) {
2818
2819         pic16_emitcode("mov","_spx,%s",r->name);
2820         pic16_freeAsmop(NULL,aop,ic,TRUE);
2821
2822     }
2823 #endif 
2824 }
2825
2826 /*-----------------------------------------------------------------*/
2827 /* saverbank - saves an entire register bank on the stack          */
2828 /*-----------------------------------------------------------------*/
2829 static void saverbank (int bank, iCode *ic, bool pushPsw)
2830 {
2831   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2832 #if 0
2833     int i;
2834     asmop *aop ;
2835     regs *r = NULL;
2836
2837     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2838     if (options.useXstack) {
2839
2840         aop = newAsmop(0);
2841         r = getFreePtr(ic,&aop,FALSE);  
2842         pic16_emitcode("mov","%s,_spx",r->name);
2843
2844     }
2845
2846     for (i = 0 ; i < pic16_nRegs ;i++) {
2847         if (options.useXstack) {
2848             pic16_emitcode("inc","%s",r->name);
2849             //pic16_emitcode("mov","a,(%s+%d)",
2850             //         regspic16[i].base,8*bank+regspic16[i].offset);
2851             pic16_emitcode("movx","@%s,a",r->name);           
2852         } else 
2853           pic16_emitcode("push","");// "(%s+%d)",
2854                      //regspic16[i].base,8*bank+regspic16[i].offset);
2855     }
2856     
2857     if (pushPsw) {
2858         if (options.useXstack) {
2859             pic16_emitcode("mov","a,psw");
2860             pic16_emitcode("movx","@%s,a",r->name);     
2861             pic16_emitcode("inc","%s",r->name);
2862             pic16_emitcode("mov","_spx,%s",r->name);       
2863             pic16_freeAsmop (NULL,aop,ic,TRUE);
2864             
2865         } else
2866             pic16_emitcode("push","psw");
2867         
2868         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2869     }
2870     ic->bankSaved = 1;
2871 #endif
2872 }
2873
2874
2875
2876 /*-----------------------------------------------------------------*/
2877 /* genCall - generates a call statement                            */
2878 /*-----------------------------------------------------------------*/
2879 static void genCall (iCode *ic)
2880 {
2881   sym_link *dtype;   
2882   int stackParms=0;
2883   
2884         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2885
2886         /* if caller saves & we have not saved then */
2887         if (!ic->regsSaved)
2888                 saveRegisters(ic);
2889
2890         /* if we are calling a function that is not using
2891          * the same register bank then we need to save the
2892          * destination registers on the stack */
2893         dtype = operandType(IC_LEFT(ic));
2894         if (currFunc && dtype && 
2895                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2896                 IFFUNC_ISISR(currFunc->type) &&
2897                 !ic->bankSaved) 
2898
2899                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2900
2901
2902         /* initialise stackParms for IPUSH pushes */
2903 //      stackParms = psuedoStkPtr;
2904 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
2905
2906         /* if send set is not empty the assign */
2907         if (_G.sendSet) {
2908           iCode *sic;
2909
2910                 /* For the Pic port, there is no data stack.
2911                  * So parameters passed to functions are stored
2912                  * in registers. (The pCode optimizer will get
2913                  * rid of most of these :). */
2914
2915           int psuedoStkPtr=-1; 
2916           int firstTimeThruLoop = 1;
2917
2918                 _G.sendSet = reverseSet(_G.sendSet);
2919
2920                 /* First figure how many parameters are getting passed */
2921                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2922                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2923                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2924                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2925                 }
2926
2927                 stackParms = psuedoStkPtr;
2928
2929                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2930                   int size, offset = 0;
2931
2932                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2933                         size = AOP_SIZE(IC_LEFT(sic));
2934
2935                         while (size--) {
2936                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2937                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2938                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2939
2940                                 if(!firstTimeThruLoop) {
2941                                         /* If this is not the first time we've been through the loop
2942                                          * then we need to save the parameter in a temporary
2943                                          * register. The last byte of the last parameter is
2944                                          * passed in W. */
2945
2946                                         pushw();
2947                                         --psuedoStkPtr;         // sanity check
2948                                 }
2949                         
2950                                 firstTimeThruLoop=0;
2951
2952                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2953                                 offset++;
2954                         }
2955                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2956                 }
2957                 _G.sendSet = NULL;
2958         }
2959
2960         /* make the call */
2961         pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2962                         OP_SYMBOL(IC_LEFT(ic))->rname :
2963                         OP_SYMBOL(IC_LEFT(ic))->name));
2964
2965         GpsuedoStkPtr=0;
2966         /* if we need assign a result value */
2967         if ((IS_ITEMP(IC_RESULT(ic)) && 
2968                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2969                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2970                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2971
2972                 _G.accInUse++;
2973                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2974                 _G.accInUse--;
2975
2976                 assignResultValue(IC_RESULT(ic), 1);
2977
2978                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2979                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2980                 
2981                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2982         }
2983
2984         if(!stackParms && ic->parmBytes) {
2985                 stackParms = ic->parmBytes;
2986         }
2987         
2988         if(stackParms>0) {
2989                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2990                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2991                 if(STACK_MODEL_LARGE) {
2992                         emitSKPNC;
2993                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2994                 }
2995         }
2996
2997         /* adjust the stack for parameters if required */
2998 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2999 #if 0
3000         if (ic->parmBytes) {
3001           int i;
3002
3003                 if (ic->parmBytes > 3) {
3004                         pic16_emitcode("mov","a,%s",spname);
3005                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3006                         pic16_emitcode("mov","%s,a",spname);
3007                 } else 
3008                         for ( i = 0 ; i <  ic->parmBytes ;i++)
3009                                 pic16_emitcode("dec","%s",spname);
3010         }
3011 #endif
3012
3013 #if 0
3014         /* if register bank was saved then pop them */
3015         if (ic->bankSaved)
3016                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3017
3018         /* if we hade saved some registers then unsave them */
3019         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3020                 unsaveRegisters (ic);
3021 #endif
3022 }
3023
3024
3025
3026 /*-----------------------------------------------------------------*/   // patch 14
3027 /* genPcall - generates a call by pointer statement                */
3028 /*-----------------------------------------------------------------*/
3029
3030 // new version, created from genCall
3031
3032 static void genPcall (iCode *ic)
3033 {
3034   sym_link *dtype;   
3035   int stackParms=0;
3036   symbol *retlbl = newiTempLabel(NULL);
3037   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3038   
3039         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3040
3041         /* if caller saves & we have not saved then */
3042         if (!ic->regsSaved)
3043                 saveRegisters(ic);
3044
3045         /* if we are calling a function that is not using
3046          * the same register bank then we need to save the
3047          * destination registers on the stack */
3048         dtype = operandType(IC_LEFT(ic));
3049         if (currFunc && dtype && 
3050                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
3051                 IFFUNC_ISISR(currFunc->type) &&
3052                 !ic->bankSaved) 
3053
3054                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3055
3056         /* if send set is not empty the assign */
3057         if (_G.sendSet) {
3058           iCode *sic;
3059
3060                 /* For the Pic port, there is no data stack.
3061                  * So parameters passed to functions are stored
3062                  * in registers. (The pCode optimizer will get
3063                  * rid of most of these :). */
3064
3065           int psuedoStkPtr=-1; 
3066           int firstTimeThruLoop = 1;
3067
3068                 _G.sendSet = reverseSet(_G.sendSet);
3069
3070                 /* First figure how many parameters are getting passed */
3071                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3072                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3073                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
3074                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
3075                 }
3076
3077                 stackParms = psuedoStkPtr;
3078
3079                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3080                   int size, offset = 0;
3081
3082                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3083                         size = AOP_SIZE(IC_LEFT(sic));
3084
3085                         while (size--) {
3086                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3087                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3088                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3089
3090                                 if(!firstTimeThruLoop) {
3091                                         /* If this is not the first time we've been through the loop
3092                                          * then we need to save the parameter in a temporary
3093                                          * register. The last byte of the last parameter is
3094                                          * passed in W. */
3095
3096                                         pushw();
3097                                         --psuedoStkPtr;         // sanity check
3098                                 }
3099                         
3100                                 firstTimeThruLoop=0;
3101
3102                                 mov2w (AOP(IC_LEFT(sic)),  offset);
3103                                 offset++;
3104                         }
3105                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3106                 }
3107                 _G.sendSet = NULL;
3108         }
3109
3110         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3111
3112         // push return address
3113         // push $ on return stack, then replace with retlbl
3114
3115         pic16_emitpcodeNULLop(POC_PUSH);
3116
3117         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3118         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3119         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3120         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3121         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3122         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3123
3124         /* make the call by writing the pointer into pc */
3125         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3126         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3127
3128         // note: MOVFF to PCL not allowed
3129         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3130         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3131
3132
3133 //      pic16_emitpcode(POC_GOTO, pic16_popGetLabel(retlbl->key));
3134 //      pic16_emitpcodeNULLop(POC_NOP);
3135 //      pic16_emitpcodeNULLop(POC_NOP);
3136
3137         /* return address is here: (X) */
3138         pic16_emitpLabelFORCE(retlbl->key);
3139
3140 //      pic16_emitpcodeNULLop(POC_NOP);
3141
3142         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3143
3144         GpsuedoStkPtr=0;
3145         /* if we need assign a result value */
3146         if ((IS_ITEMP(IC_RESULT(ic)) && 
3147                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3148                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
3149                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3150
3151                 _G.accInUse++;
3152                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3153                 _G.accInUse--;
3154
3155                 assignResultValue(IC_RESULT(ic), 1);
3156
3157                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3158                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3159                 
3160                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3161         }
3162
3163         if(stackParms>0) {
3164                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3165                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3166                 if(STACK_MODEL_LARGE) {
3167                         emitSKPNC;
3168                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3169                 }
3170         }
3171
3172         /* adjust the stack for parameters if required */
3173 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3174
3175         if (ic->parmBytes) {
3176           int i;
3177
3178                 if (ic->parmBytes > 3) {
3179                         pic16_emitcode("mov","a,%s",spname);
3180                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3181                         pic16_emitcode("mov","%s,a",spname);
3182                 } else 
3183                         for ( i = 0 ; i <  ic->parmBytes ;i++)
3184                                 pic16_emitcode("dec","%s",spname);
3185         }
3186
3187         /* if register bank was saved then pop them */
3188         if (ic->bankSaved)
3189                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3190
3191         /* if we hade saved some registers then unsave them */
3192         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3193                 unsaveRegisters (ic);
3194 }
3195
3196
3197 #if 0                                                                           // patch 14
3198 // old version, kept for reference
3199
3200 /*-----------------------------------------------------------------*/
3201 /* genPcall - generates a call by pointer statement                */
3202 /*-----------------------------------------------------------------*/
3203 static void genPcall (iCode *ic)
3204 {
3205     sym_link *dtype;
3206     symbol *rlbl = newiTempLabel(NULL);
3207
3208
3209     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3210     /* if caller saves & we have not saved then */
3211     if (!ic->regsSaved)
3212         saveRegisters(ic);
3213
3214     /* if we are calling a function that is not using
3215     the same register bank then we need to save the
3216     destination registers on the stack */
3217     dtype = operandType(IC_LEFT(ic));
3218     if (currFunc && dtype && 
3219         IFFUNC_ISISR(currFunc->type) &&
3220         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3221         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3222
3223
3224     /* push the return address on to the stack */
3225     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3226     pic16_emitcode("push","acc");    
3227     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3228     pic16_emitcode("push","acc");
3229     
3230     if (options.model == MODEL_FLAT24)
3231     {
3232         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3233         pic16_emitcode("push","acc");    
3234     }
3235
3236     /* now push the calling address */
3237     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3238
3239     pushSide(IC_LEFT(ic), FPTRSIZE);
3240
3241     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
3242
3243     /* if send set is not empty the assign */
3244     if (_G.sendSet) {
3245         iCode *sic ;
3246
3247         for (sic = setFirstItem(_G.sendSet) ; sic ; 
3248              sic = setNextItem(_G.sendSet)) {
3249             int size, offset = 0;
3250             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3251             size = AOP_SIZE(IC_LEFT(sic));
3252             while (size--) {
3253                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3254                                 FALSE,FALSE);
3255                 if (strcmp(l,fReturn[offset]))
3256                     pic16_emitcode("mov","%s,%s",
3257                              fReturn[offset],
3258                              l);
3259                 offset++;
3260             }
3261             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3262         }
3263         _G.sendSet = NULL;
3264     }
3265
3266     pic16_emitcode("ret","");
3267     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3268
3269
3270     /* if we need assign a result value */
3271     if ((IS_ITEMP(IC_RESULT(ic)) &&
3272          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3273           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3274         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3275
3276         _G.accInUse++;
3277         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3278         _G.accInUse--;
3279         
3280         assignResultValue(IC_RESULT(ic), 1);
3281
3282         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3283     }
3284
3285     /* adjust the stack for parameters if 
3286     required */
3287     if (ic->parmBytes) {
3288         int i;
3289         if (ic->parmBytes > 3) {
3290             pic16_emitcode("mov","a,%s",spname);
3291             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3292             pic16_emitcode("mov","%s,a",spname);
3293         } else 
3294             for ( i = 0 ; i <  ic->parmBytes ;i++)
3295                 pic16_emitcode("dec","%s",spname);
3296
3297     }
3298
3299     /* if register bank was saved then unsave them */
3300     if (currFunc && dtype && 
3301         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3302         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3303
3304     /* if we hade saved some registers then
3305     unsave them */
3306     if (ic->regsSaved)
3307         unsaveRegisters (ic);
3308
3309 }
3310 #endif                                                                          // patch 14
3311
3312
3313 /*-----------------------------------------------------------------*/
3314 /* resultRemat - result  is rematerializable                       */
3315 /*-----------------------------------------------------------------*/
3316 static int resultRemat (iCode *ic)
3317 {
3318   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3319   if (SKIP_IC(ic) || ic->op == IFX)
3320     return 0;
3321
3322   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3323     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3324     if (sym->remat && !POINTER_SET(ic)) 
3325       return 1;
3326   }
3327
3328   return 0;
3329 }
3330
3331 #if defined(__BORLANDC__) || defined(_MSC_VER)
3332 #define STRCASECMP stricmp
3333 #else
3334 #define STRCASECMP strcasecmp
3335 #endif
3336
3337 #if 0
3338 /*-----------------------------------------------------------------*/
3339 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3340 /*-----------------------------------------------------------------*/
3341 static bool inExcludeList(char *s)
3342 {
3343   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3344     int i =0;
3345     
3346     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3347     if (options.excludeRegs[i] &&
3348     STRCASECMP(options.excludeRegs[i],"none") == 0)
3349         return FALSE ;
3350
3351     for ( i = 0 ; options.excludeRegs[i]; i++) {
3352         if (options.excludeRegs[i] &&
3353         STRCASECMP(s,options.excludeRegs[i]) == 0)
3354             return TRUE;
3355     }
3356     return FALSE ;
3357 }
3358 #endif
3359
3360 /*-----------------------------------------------------------------*/
3361 /* genFunction - generated code for function entry                 */
3362 /*-----------------------------------------------------------------*/
3363 static void genFunction (iCode *ic)
3364 {
3365   symbol *sym;
3366   sym_link *ftype;
3367   
3368         DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3369
3370         pic16_labelOffset += (max_key+4);
3371         max_key=0;
3372         GpsuedoStkPtr=0;
3373         _G.nRegsSaved = 0;
3374
3375         ftype = operandType(IC_LEFT(ic));
3376         sym = OP_SYMBOL(IC_LEFT(ic));
3377
3378         if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3379                 /* create an absolute section at the interrupt vector:
3380                  * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3381           symbol *asym;
3382           char asymname[128];
3383           pBlock *apb;
3384
3385                 {
3386                   int i, found=-1;
3387
3388                         sym = OP_SYMBOL( IC_LEFT(ic));
3389                         for(i=0;i<=2;i++) {
3390                                 if(interrupts[i]->name
3391                                         && !STRCASECMP(interrupts[i]->name, sym->name)) {
3392                                         found = i;
3393                                         break;
3394                                 }
3395                         }
3396                         
3397                         if(found == -1) {
3398                                 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3399                                         __FILE__, __LINE__, sym->name);
3400                                 assert( 0 );
3401                         }
3402                         _G.interruptvector = found;
3403                 }
3404
3405                 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3406                 asym = newSymbol(asymname, 0);
3407
3408                 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3409                 pic16_addpBlock( apb );
3410
3411                 pic16_addpCode2pBlock(apb,
3412                         pic16_newpCodeCharP(";-----------------------------------------"));
3413
3414
3415                 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3416
3417                 pic16_addpCode2pBlock(apb,
3418                         pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3419                 
3420                 /* mark the end of this tiny function */
3421                 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3422
3423                 {
3424                   absSym *abSym;
3425
3426                         abSym = Safe_calloc(1, sizeof(absSym));
3427                         abSym->name = Safe_strdup( asymname );
3428
3429                         switch( _G.interruptvector ) {
3430                                 case 0: abSym->address = 0x000000; break;
3431                                 case 1: abSym->address = 0x000008; break;
3432                                 case 2: abSym->address = 0x000018; break;
3433                         }
3434
3435                         /* relocate interrupt vectors if needed */
3436                         abSym->address += pic16_options.ivt_loc;
3437
3438                         addSet(&absSymSet, abSym);
3439                 }
3440         }
3441
3442
3443         /* create the function header */
3444         pic16_emitcode(";","-----------------------------------------");
3445         pic16_emitcode(";"," function %s",sym->name);
3446         pic16_emitcode(";","-----------------------------------------");
3447
3448         pic16_emitcode("","%s:",sym->rname);
3449         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3450
3451
3452         {
3453           absSym *ab;
3454
3455                 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3456                         if(!strcmp(ab->name, sym->name)) {
3457                                 pic16_pBlockConvert2Absolute(pb);
3458                                 break;
3459                         }
3460
3461         }
3462
3463
3464         if(IFFUNC_ISNAKED(ftype)) {
3465                 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3466                 return;
3467         }
3468         
3469         /* if critical function then turn interrupts off */
3470         if (IFFUNC_ISCRITICAL(ftype))
3471                 pic16_emitcode("clr","ea");
3472
3473         /* if this is an interrupt service routine then
3474          * save acc, b, dpl, dph  */
3475         if (IFFUNC_ISISR(sym->type)) {
3476           int i;
3477
3478                 _G.usefastretfie = 1;   /* use shadow registers by default */
3479                 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3480                 if(!(_G.interruptvector == 1)) {
3481
3482                         /* do not save WREG,STATUS,BSR for high priority interrupts
3483                          * because they are stored in the hardware shadow registers already */
3484                         _G.usefastretfie = 0;
3485                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3486                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3487                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3488                 }
3489
3490
3491                 /* these should really be optimized somehow, because not all
3492                  * interrupt handlers modify them */
3493                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3494                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3495                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3496                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3497
3498 //                pic16_pBlockConvert2ISR(pb);
3499                 
3500                 /* if any registers used */
3501                 if (sym->regsUsed) {
3502                         /* save the registers used */
3503                         DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3504                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3505                                 if (bitVectBitValue(sym->regsUsed,i)) {
3506 #if 0
3507                                         fprintf(stderr, "%s:%d function %s uses register %s\n",
3508                                                         __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3509                                                         pic16_regWithIdx(i)->name);
3510 #endif
3511
3512                                         pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3513                                         _G.nRegsSaved++;
3514
3515                                         if(!pic16_regWithIdx(i)->wasUsed) {
3516                                                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3517                                                         __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3518
3519                                                 pic16_regWithIdx(i)->wasUsed = 1;
3520                                         }
3521                                 }
3522                         }
3523                 }
3524         } else {
3525                 /* emit code to setup stack frame if user enabled,
3526                  * and function is not main() */
3527          
3528 //              fprintf(stderr, "function name: %s\n", sym->name);
3529                 if(strcmp(sym->name, "main")) {
3530                         if(/*!options.ommitFramePtr || */sym->regsUsed) {
3531                         /* setup the stack frame */
3532                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3533                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3534                                 if(STACK_MODEL_LARGE)
3535                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3536                         }
3537                 }
3538
3539                 /* if callee-save to be used for this function
3540                 * then save the registers being used in this function */
3541 //              if (IFFUNC_CALLEESAVES(sym->type))
3542                 {
3543                   int i;
3544
3545 //                      fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3546
3547 //                      pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3548
3549                         /* if any registers used */
3550                         if (sym->regsUsed) {
3551                                 /* save the registers used */
3552                                 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3553                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3554                                         if (bitVectBitValue(sym->regsUsed,i)) {
3555
3556 #if 0
3557                                                 fprintf(stderr, "%s:%d function %s uses register %s (wasUsed: %d, %p)\n",
3558                                                                 __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3559                                                                 pic16_regWithIdx(i)->name,
3560                                                                 pic16_regWithIdx(i)->wasUsed,
3561                                                                 pic16_regWithIdx(i));
3562 #endif
3563
3564                                                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3565
3566 //                                              pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3567 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3568 //                                                      &pic16_pc_postdec1, 0));
3569
3570                                                 _G.nRegsSaved++;
3571
3572                                                 if(!pic16_regWithIdx(i)->wasUsed) {
3573                                                         fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3574                                                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3575
3576                                                         pic16_regWithIdx(i)->wasUsed = 1;
3577                                                 }
3578                                         
3579                                         }
3580                                 }
3581                         }
3582                 }
3583         }
3584
3585
3586         
3587 #if 0
3588         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3589
3590                 if (options.useXstack) {
3591                         pic16_emitcode("mov","r0,%s",spname);
3592                         pic16_emitcode("mov","a,_bp");
3593                         pic16_emitcode("movx","@r0,a");
3594                         pic16_emitcode("inc","%s",spname);
3595                 } else {
3596                         /* set up the stack */
3597                         pic16_emitcode ("push","_bp");     /* save the callers stack  */
3598                 }
3599                 pic16_emitcode ("mov","_bp,%s",spname);
3600         }
3601 #endif
3602         DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3603
3604         /* adjust the stack for the function */
3605         if (sym->stack) {
3606           int i = sym->stack;
3607
3608                 if (i > 127 ) 
3609                         werror(W_STACK_OVERFLOW,sym->name);
3610
3611                 if (i > 3 && sym->recvSize < 4) {              
3612                         pic16_emitcode ("mov","a,sp");
3613                         pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3614                         pic16_emitcode ("mov","sp,a");
3615                 } else
3616                         while(i--)
3617                                 pic16_emitcode("inc","sp");
3618         }
3619
3620         if (sym->xstack) {
3621                 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3622
3623                 pic16_emitcode ("mov","a,_spx");
3624                 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3625                 pic16_emitcode ("mov","_spx,a");
3626         }
3627     
3628 }
3629
3630 /*-----------------------------------------------------------------*/
3631 /* genEndFunction - generates epilogue for functions               */
3632 /*-----------------------------------------------------------------*/
3633 static void genEndFunction (iCode *ic)
3634 {
3635     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3636
3637     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3638
3639     if(IFFUNC_ISNAKED(sym->type)) {
3640         DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3641         return;
3642     }
3643
3644     /* add code for ISCRITICAL */
3645
3646 #if 0
3647     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3648     {
3649         pic16_emitcode ("mov","%s,_bp",spname);
3650     }
3651 #endif
3652
3653     /* if use external stack but some variables were
3654     added to the local stack then decrement the
3655     local stack */
3656     if (options.useXstack && sym->stack) {      
3657         pic16_emitcode("mov","a,sp");
3658         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3659         pic16_emitcode("mov","sp,a");
3660     }
3661
3662
3663 #if 0
3664     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3665         if (options.useXstack) {
3666             pic16_emitcode("mov","r0,%s",spname);
3667             pic16_emitcode("movx","a,@r0");
3668             pic16_emitcode("mov","_bp,a");
3669             pic16_emitcode("dec","%s",spname);
3670         }
3671         else
3672         {
3673             pic16_emitcode ("pop","_bp");
3674         }
3675     }
3676 #endif
3677
3678         if (IFFUNC_ISISR(sym->type)) {
3679                 /* now we need to restore the registers */
3680                 /* if any registers used */
3681                 if (sym->regsUsed) {
3682                   int i;
3683
3684                         /* restore registers used */
3685                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3686                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3687                                 if (bitVectBitValue(sym->regsUsed,i)) {
3688
3689 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3690 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3691 //                                                      pic16_regWithIdx(i)->name);
3692
3693                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3694
3695 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3696 //                                                      &pic16_pc_preinc1,
3697 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3698
3699                                 }
3700                         }
3701                 }
3702         
3703                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3704                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3705                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3706                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3707
3708                 if(!(_G.interruptvector == 1)) {
3709                         /* do not restore interrupt vector for WREG,STATUS,BSR
3710                          * for high priority interrupt, see genFunction */
3711                          
3712                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3713                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3714                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3715                 }
3716         
3717                 _G.interruptvector = 0;         /* sanity check */
3718
3719 //              pic16_pBlockConvert2ISR(pb);
3720
3721
3722                 /* if debug then send end of function */
3723 /*      if (options.debug && currFunc)  */
3724                 if (currFunc) {
3725                         debugFile->writeEndFunction (currFunc, ic, 1);
3726                 }
3727         
3728                 if(_G.usefastretfie)
3729                         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3730                 else
3731                 pic16_emitpcodeNULLop(POC_RETFIE);
3732                 _G.usefastretfie = 0;
3733         } else {
3734                 if (IFFUNC_ISCRITICAL(sym->type))
3735                         pic16_emitcode("setb","ea");
3736         
3737
3738 //              pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3739
3740                 /* if any registers used */
3741                 if (sym->regsUsed) {
3742                   int i;
3743                         /* save the registers used */
3744                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3745                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3746                                 if (bitVectBitValue(sym->regsUsed,i)) {
3747         
3748 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3749 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3750 //                                                      pic16_regWithIdx(i)->name);
3751         
3752                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3753                                         
3754 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3755 //                                              &pic16_pc_preinc1,
3756 //                                              PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3757
3758                                         _G.nRegsSaved--;
3759                                 }
3760                         }
3761                 }
3762         
3763 //              pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3764                 /* if debug then send end of function */
3765                 if (currFunc) {
3766                         debugFile->writeEndFunction (currFunc, ic, 1);
3767                 }
3768
3769                 /* insert code to restore stack frame, if user enabled it
3770                  * and function is not main() */
3771          
3772
3773                 if(strcmp(sym->name, "main")) {
3774                         if(/*!options.ommitFramePtr ||*/ sym->regsUsed) {
3775                                 /* restore stack frame */
3776                                 if(STACK_MODEL_LARGE)
3777                                         pic16_emitpcode(POC_MOVFF,
3778                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3779                                 pic16_emitpcode(POC_MOVFF,
3780                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3781                         }
3782                 }
3783
3784                 pic16_emitpcodeNULLop(POC_RETURN);
3785
3786                 /* Mark the end of a function */
3787                 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3788         }
3789
3790 }
3791
3792
3793 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3794 {
3795
3796         if(is_LitOp(op)) {
3797                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3798
3799                 if(dest->type != PO_WREG)
3800                         pic16_emitpcode(POC_MOVWF, dest);
3801         } else {
3802                 if(dest->type == PO_WREG && (offset == 0)) {
3803                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3804                         return;
3805                 }
3806                 
3807                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3808                         pic16_popGet(AOP(op), offset), dest));
3809         }
3810 }
3811
3812 /*-----------------------------------------------------------------*/
3813 /* genRet - generate code for return statement                     */
3814 /*-----------------------------------------------------------------*/
3815 static void genRet (iCode *ic)
3816 {
3817   int size;
3818   operand *left;
3819
3820         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3821         /* if we have no return value then
3822          * just generate the "ret" */
3823         
3824         if (!IC_LEFT(ic)) 
3825                 goto jumpret;       
3826     
3827         /* we have something to return then
3828          * move the return value into place */
3829         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3830         size = AOP_SIZE(IC_LEFT(ic));
3831
3832         if(size <= 4) {
3833                 if(size>3) {
3834                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3835 //                      pic16_emitpcode(POC_MOVFF,
3836 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3837                 }
3838                 if(size>2) {
3839                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3840 //                      pic16_emitpcode(POC_MOVFF,
3841 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3842                 }
3843                 if(size>1) {
3844                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3845 //                      pic16_emitpcode(POC_MOVFF,
3846 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3847                 }
3848
3849 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3850
3851                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3852 //              pic16_emitpcode(POC_MOVFF,
3853 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3854
3855         } else {
3856                 /* >32-bits, setup stack and FSR0 */
3857                 while (size--) {
3858 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3859 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3860
3861                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3862
3863 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3864                         GpsuedoStkPtr++;
3865                 }
3866                         
3867                 /* setup FSR0 */
3868                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3869                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3870
3871                 if(STACK_MODEL_LARGE) {
3872                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3873                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3874                 } else {
3875                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3876                 }
3877         }
3878                                 
3879 #if 0
3880         /* old code, left here for reference -- VR */    
3881         while (size--) {
3882           char *l ;
3883
3884                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3885                         /* #NOCHANGE */
3886                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3887                         pic16_emitpcomment("push %s",l);
3888                         pushed++;
3889                 } else {
3890                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3891                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3892                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3893                         
3894                         if (strcmp(fReturn[offset],l)) {
3895                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3896                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3897                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3898                                 } else {
3899                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3900                                 }
3901                                 
3902                                 if(size) {
3903                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3904                                 }
3905                                 offset++;
3906                         }
3907                 }
3908         }    
3909
3910         if (pushed) {
3911                 while(pushed) {
3912                         pushed--;
3913                         if (strcmp(fReturn[pushed],"a"))
3914                                 pic16_emitcode("pop",fReturn[pushed]);
3915                         else
3916                                 pic16_emitcode("pop","acc");
3917                 }
3918         }
3919 #endif
3920
3921
3922         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3923     
3924 jumpret:
3925         /* generate a jump to the return label
3926          * if the next is not the return statement */
3927         if (!(ic->next && ic->next->op == LABEL
3928                 && IC_LABEL(ic->next) == returnLabel)) {
3929         
3930                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3931                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3932         }
3933 }
3934
3935 /*-----------------------------------------------------------------*/
3936 /* genLabel - generates a label                                    */
3937 /*-----------------------------------------------------------------*/
3938 static void genLabel (iCode *ic)
3939 {
3940
3941
3942     /* special case never generate */
3943     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3944     if (IC_LABEL(ic) == entryLabel)
3945         return ;
3946
3947     pic16_emitpLabel(IC_LABEL(ic)->key);
3948     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3949 }
3950
3951 /*-----------------------------------------------------------------*/
3952 /* genGoto - generates a goto                                      */
3953 /*-----------------------------------------------------------------*/
3954 //tsd
3955 static void genGoto (iCode *ic)
3956 {
3957   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3958   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3959 }
3960
3961
3962 /*-----------------------------------------------------------------*/
3963 /* genMultbits :- multiplication of bits                           */
3964 /*-----------------------------------------------------------------*/
3965 static void genMultbits (operand *left, 
3966                          operand *right, 
3967                          operand *result)
3968 {
3969   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3970
3971   if(!pic16_sameRegs(AOP(result),AOP(right)))
3972     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3973
3974   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3975   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3976   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3977
3978 }
3979
3980
3981 /*-----------------------------------------------------------------*/
3982 /* genMultOneByte : 8 bit multiplication & division                */
3983 /*-----------------------------------------------------------------*/
3984 static void genMultOneByte (operand *left,
3985                             operand *right,
3986                             operand *result)
3987 {
3988
3989   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3990   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3991   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3992
3993   /* (if two literals, the value is computed before) */
3994   /* if one literal, literal on the right */
3995   if (AOP_TYPE(left) == AOP_LIT){
3996     operand *t = right;
3997     right = left;
3998     left = t;
3999   }
4000
4001         /* size is already checked in genMult == 1 */
4002 //      size = AOP_SIZE(result);
4003
4004         if (AOP_TYPE(right) == AOP_LIT){
4005                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4006                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4007                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4008                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4009         } else {
4010                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4011                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4012                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4013                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4014         }
4015         
4016         pic16_genMult8X8_8 (left, right,result);
4017 }
4018
4019 /*-----------------------------------------------------------------*/
4020 /* genMultOneWord : 16 bit multiplication                          */
4021 /*-----------------------------------------------------------------*/
4022 static void genMultOneWord (operand *left,
4023                             operand *right,
4024                             operand *result)
4025 {
4026
4027         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4028         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4029         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4030
4031         /* (if two literals, the value is computed before)
4032          * if one literal, literal on the right */
4033         if (AOP_TYPE(left) == AOP_LIT){
4034           operand *t = right;
4035                 right = left;
4036                 left = t;
4037         }
4038
4039         /* size is checked already == 2 */
4040 //      size = AOP_SIZE(result);
4041
4042         if (AOP_TYPE(right) == AOP_LIT) {
4043                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4044                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4045                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4046                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4047         } else {
4048                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4049                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4050                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4051                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4052         }
4053         
4054         pic16_genMult16X16_16(left, right,result);
4055 }
4056
4057 /*-----------------------------------------------------------------*/
4058 /* genMultOneLong : 32 bit multiplication                          */
4059 /*-----------------------------------------------------------------*/
4060 static void genMultOneLong (operand *left,
4061                             operand *right,
4062                             operand *result)
4063 {
4064
4065         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4066         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4067         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4068
4069         /* (if two literals, the value is computed before)
4070          * if one literal, literal on the right */
4071         if (AOP_TYPE(left) == AOP_LIT){
4072           operand *t = right;
4073                 right = left;
4074                 left = t;
4075         }
4076
4077         /* size is checked already == 4 */
4078 //      size = AOP_SIZE(result);
4079
4080         if (AOP_TYPE(right) == AOP_LIT) {
4081                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4082                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4083                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4084                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4085         } else {
4086                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4087                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4088                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4089                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4090         }
4091         
4092         pic16_genMult32X32_32(left, right,result);
4093 }
4094
4095
4096
4097 /*-----------------------------------------------------------------*/
4098 /* genMult - generates code for multiplication                     */
4099 /*-----------------------------------------------------------------*/
4100 static void genMult (iCode *ic)
4101 {
4102   operand *left = IC_LEFT(ic);
4103   operand *right = IC_RIGHT(ic);
4104   operand *result= IC_RESULT(ic);   
4105
4106         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4107         /* assign the amsops */
4108         pic16_aopOp (left,ic,FALSE);
4109         pic16_aopOp (right,ic,FALSE);
4110         pic16_aopOp (result,ic,TRUE);
4111
4112         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4113
4114         /* special cases first *
4115         * both are bits */
4116         if (AOP_TYPE(left) == AOP_CRY
4117                 && AOP_TYPE(right)== AOP_CRY) {
4118                 genMultbits(left,right,result);
4119           goto release ;
4120         }
4121
4122         /* if both are of size == 1 */
4123         if(AOP_SIZE(left) == 1
4124                 && AOP_SIZE(right) == 1) {
4125                 genMultOneByte(left,right,result);
4126           goto release ;
4127         }
4128
4129         /* if both are of size == 2 */
4130         if(AOP_SIZE(left) == 2
4131                 && AOP_SIZE(right) == 2) {
4132                 genMultOneWord(left, right, result);
4133           goto release;
4134         }
4135         
4136         /* if both are of size == 4 */
4137         if(AOP_SIZE(left) == 4
4138                 && AOP_SIZE(right) == 4) {
4139                 genMultOneLong(left, right, result);
4140           goto release;
4141         }
4142         
4143         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4144
4145
4146         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4147         /* should have been converted to function call */
4148         assert(0) ;
4149
4150 release :
4151         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4152         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4153         pic16_freeAsmop(result,NULL,ic,TRUE); 
4154 }
4155
4156 /*-----------------------------------------------------------------*/
4157 /* genDivbits :- division of bits                                  */
4158 /*-----------------------------------------------------------------*/
4159 static void genDivbits (operand *left, 
4160                         operand *right, 
4161                         operand *result)
4162 {
4163
4164     char *l;
4165
4166     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4167     /* the result must be bit */    
4168     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4169     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4170
4171     MOVA(l);    
4172
4173     pic16_emitcode("div","ab");
4174     pic16_emitcode("rrc","a");
4175     pic16_aopPut(AOP(result),"c",0);
4176 }
4177
4178 /*-----------------------------------------------------------------*/
4179 /* genDivOneByte : 8 bit division                                  */
4180 /*-----------------------------------------------------------------*/
4181 static void genDivOneByte (operand *left,
4182                            operand *right,
4183                            operand *result)
4184 {
4185     sym_link *opetype = operandType(result);
4186     char *l ;
4187     symbol *lbl ;
4188     int size,offset;
4189
4190         /* result = divident / divisor
4191          * - divident may be a register or a literal,
4192          * - divisor may be a register or a literal,
4193          * so there are 3 cases (literal / literal is optimized
4194          * by the front-end) to handle.
4195          * In addition we must handle signed and unsigned, which
4196          * result in 6 final different cases -- VR */
4197
4198     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4199     size = AOP_SIZE(result) - 1;
4200     offset = 1;
4201     /* signed or unsigned */
4202     if (SPEC_USIGN(opetype)) {
4203       pCodeOp *pct1,    /* count */
4204                 *pct2,  /* reste */
4205                 *pct3;  /* temp */
4206       symbol *label1, *label2, *label3;;
4207
4208
4209         /* unsigned is easy */
4210
4211         pct1 = pic16_popGetTempReg();
4212         pct2 = pic16_popGetTempReg();
4213         pct3 = pic16_popGetTempReg();
4214         
4215         label1 = newiTempLabel(NULL);
4216         label2 = newiTempLabel(NULL);
4217         label3 = newiTempLabel(NULL);
4218
4219         /* the following algorithm is extracted from divuint.c */
4220
4221         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4222         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4223         
4224         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4225
4226         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4227         
4228         pic16_emitpLabel(label1->key);
4229         
4230         emitCLRC;
4231         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4232
4233
4234         emitCLRC;
4235         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4236         
4237
4238         emitSKPNC;
4239         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4240         
4241         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4242         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4243         
4244         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4245         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4246         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4247         
4248         pic16_emitpLabel( label3->key );
4249         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4250         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4251         
4252         
4253
4254         pic16_emitpLabel(label2->key);
4255         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4256         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4257         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4258         
4259         /* result is in wreg */
4260         if(AOP_TYPE(result) != AOP_ACC)
4261                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4262
4263         pic16_popReleaseTempReg( pct3 );
4264         pic16_popReleaseTempReg( pct2 );
4265         pic16_popReleaseTempReg( pct1 );
4266
4267         return ;
4268     }
4269
4270     /* signed is a little bit more difficult */
4271
4272     /* save the signs of the operands */
4273     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4274     MOVA(l);    
4275     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4276     pic16_emitcode("push","acc"); /* save it on the stack */
4277
4278     /* now sign adjust for both left & right */
4279     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4280     MOVA(l);       
4281     lbl = newiTempLabel(NULL);
4282     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4283     pic16_emitcode("cpl","a");   
4284     pic16_emitcode("inc","a");
4285     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4286     pic16_emitcode("mov","b,a");
4287
4288     /* sign adjust left side */
4289     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4290     MOVA(l);
4291
4292     lbl = newiTempLabel(NULL);
4293     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4294     pic16_emitcode("cpl","a");
4295     pic16_emitcode("inc","a");
4296     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4297
4298     /* now the division */
4299     pic16_emitcode("div","ab");
4300     /* we are interested in the lower order
4301     only */
4302     pic16_emitcode("mov","b,a");
4303     lbl = newiTempLabel(NULL);
4304     pic16_emitcode("pop","acc");   
4305     /* if there was an over flow we don't 
4306     adjust the sign of the result */
4307     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4308     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4309     CLRC;
4310     pic16_emitcode("clr","a");
4311     pic16_emitcode("subb","a,b");
4312     pic16_emitcode("mov","b,a");
4313     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4314
4315     /* now we are done */
4316     pic16_aopPut(AOP(result),"b",0);
4317     if(size > 0){
4318         pic16_emitcode("mov","c,b.7");
4319         pic16_emitcode("subb","a,acc");   
4320     }
4321     while (size--)
4322         pic16_aopPut(AOP(result),"a",offset++);
4323
4324 }
4325
4326 /*-----------------------------------------------------------------*/
4327 /* genDiv - generates code for division                            */
4328 /*-----------------------------------------------------------------*/
4329 static void genDiv (iCode *ic)
4330 {
4331     operand *left = IC_LEFT(ic);
4332     operand *right = IC_RIGHT(ic);
4333     operand *result= IC_RESULT(ic);   
4334
4335
4336         /* Division is a very lengthy algorithm, so it is better
4337          * to call support routines than inlining algorithm.
4338          * Division functions written here just in case someone
4339          * wants to inline and not use the support libraries -- VR */
4340
4341     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4342     /* assign the amsops */
4343     pic16_aopOp (left,ic,FALSE);
4344     pic16_aopOp (right,ic,FALSE);
4345     pic16_aopOp (result,ic,TRUE);
4346
4347     /* special cases first */
4348     /* both are bits */
4349     if (AOP_TYPE(left) == AOP_CRY &&
4350         AOP_TYPE(right)== AOP_CRY) {
4351         genDivbits(left,right,result);
4352         goto release ;
4353     }
4354
4355     /* if both are of size == 1 */
4356     if (AOP_SIZE(left) == 1 &&
4357         AOP_SIZE(right) == 1 ) {
4358         genDivOneByte(left,right,result);
4359         goto release ;
4360     }
4361
4362     /* should have been converted to function call */
4363     assert(0);
4364 release :
4365     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4366     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4367     pic16_freeAsmop(result,NULL,ic,TRUE); 
4368 }
4369
4370 /*-----------------------------------------------------------------*/
4371 /* genModbits :- modulus of bits                                   */
4372 /*-----------------------------------------------------------------*/
4373 static void genModbits (operand *left, 
4374                         operand *right, 
4375                         operand *result)
4376 {
4377
4378     char *l;
4379
4380     /* the result must be bit */    
4381     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4382     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4383
4384     MOVA(l);       
4385
4386     pic16_emitcode("div","ab");
4387     pic16_emitcode("mov","a,b");
4388     pic16_emitcode("rrc","a");
4389     pic16_aopPut(AOP(result),"c",0);
4390 }
4391
4392 /*-----------------------------------------------------------------*/
4393 /* genModOneByte : 8 bit modulus                                   */
4394 /*-----------------------------------------------------------------*/
4395 static void genModOneByte (operand *left,
4396                            operand *right,
4397                            operand *result)
4398 {
4399     sym_link *opetype = operandType(result);
4400     char *l ;
4401     symbol *lbl ;
4402
4403     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4404     /* signed or unsigned */
4405     if (SPEC_USIGN(opetype)) {
4406         /* unsigned is easy */
4407         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4408         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4409         MOVA(l);    
4410         pic16_emitcode("div","ab");
4411         pic16_aopPut(AOP(result),"b",0);
4412         return ;
4413     }
4414
4415     /* signed is a little bit more difficult */
4416
4417     /* save the signs of the operands */
4418     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4419     MOVA(l);
4420
4421     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4422     pic16_emitcode("push","acc"); /* save it on the stack */
4423
4424     /* now sign adjust for both left & right */
4425     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4426     MOVA(l);
4427
4428     lbl = newiTempLabel(NULL);
4429     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4430     pic16_emitcode("cpl","a");   
4431     pic16_emitcode("inc","a");
4432     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4433     pic16_emitcode("mov","b,a"); 
4434
4435     /* sign adjust left side */
4436     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4437     MOVA(l);
4438
4439     lbl = newiTempLabel(NULL);
4440     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4441     pic16_emitcode("cpl","a");   
4442     pic16_emitcode("inc","a");
4443     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4444
4445     /* now the multiplication */
4446     pic16_emitcode("div","ab");
4447     /* we are interested in the lower order
4448     only */
4449     lbl = newiTempLabel(NULL);
4450     pic16_emitcode("pop","acc");   
4451     /* if there was an over flow we don't 
4452     adjust the sign of the result */
4453     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4454     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4455     CLRC ;
4456     pic16_emitcode("clr","a");
4457     pic16_emitcode("subb","a,b");
4458     pic16_emitcode("mov","b,a");
4459     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4460
4461     /* now we are done */
4462     pic16_aopPut(AOP(result),"b",0);
4463
4464 }
4465
4466 /*-----------------------------------------------------------------*/
4467 /* genMod - generates code for division                            */
4468 /*-----------------------------------------------------------------*/
4469 static void genMod (iCode *ic)
4470 {
4471     operand *left = IC_LEFT(ic);
4472     operand *right = IC_RIGHT(ic);
4473     operand *result= IC_RESULT(ic);  
4474
4475     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4476     /* assign the amsops */
4477     pic16_aopOp (left,ic,FALSE);
4478     pic16_aopOp (right,ic,FALSE);
4479     pic16_aopOp (result,ic,TRUE);
4480
4481     /* special cases first */
4482     /* both are bits */
4483     if (AOP_TYPE(left) == AOP_CRY &&
4484         AOP_TYPE(right)== AOP_CRY) {
4485         genModbits(left,right,result);
4486         goto release ;
4487     }
4488
4489     /* if both are of size == 1 */
4490     if (AOP_SIZE(left) == 1 &&
4491         AOP_SIZE(right) == 1 ) {
4492         genModOneByte(left,right,result);
4493         goto release ;
4494     }
4495
4496     /* should have been converted to function call */
4497     assert(0);
4498
4499 release :
4500     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4501     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4502     pic16_freeAsmop(result,NULL,ic,TRUE); 
4503 }
4504
4505 /*-----------------------------------------------------------------*/
4506 /* genIfxJump :- will create a jump depending on the ifx           */
4507 /*-----------------------------------------------------------------*/
4508 /*
4509   note: May need to add parameter to indicate when a variable is in bit space.
4510 */
4511 static void genIfxJump (iCode *ic, char *jval)
4512 {
4513
4514     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4515     /* if true label then we jump if condition
4516     supplied is true */
4517     if ( IC_TRUE(ic) ) {
4518
4519         if(strcmp(jval,"a") == 0)
4520           emitSKPZ;
4521         else if (strcmp(jval,"c") == 0)
4522           emitSKPC;
4523         else {
4524           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4525           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4526         }
4527
4528         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4529         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4530
4531     }
4532     else {
4533         /* false label is present */
4534         if(strcmp(jval,"a") == 0)
4535           emitSKPNZ;
4536         else if (strcmp(jval,"c") == 0)
4537           emitSKPNC;
4538         else {
4539           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4540           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4541         }
4542
4543         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4544         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4545
4546     }
4547
4548
4549     /* mark the icode as generated */
4550     ic->generated = 1;
4551 }
4552
4553 #if 0
4554 // not needed ATM
4555
4556 /*-----------------------------------------------------------------*/
4557 /* genSkip                                                         */
4558 /*-----------------------------------------------------------------*/
4559 static void genSkip(iCode *ifx,int status_bit)
4560 {
4561   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4562   if(!ifx)
4563     return;
4564
4565   if ( IC_TRUE(ifx) ) {
4566     switch(status_bit) {
4567     case 'z':
4568       emitSKPNZ;
4569       break;
4570
4571     case 'c':
4572       emitSKPNC;
4573       break;
4574
4575     case 'd':
4576       emitSKPDC;
4577       break;
4578
4579     }
4580
4581     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4582     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4583
4584   } else {
4585
4586     switch(status_bit) {
4587
4588     case 'z':
4589       emitSKPZ;
4590       break;
4591
4592     case 'c':
4593       emitSKPC;
4594       break;
4595
4596     case 'd':
4597       emitSKPDC;
4598       break;
4599     }
4600     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4601     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4602
4603   }
4604
4605 }
4606 #endif
4607
4608 /*-----------------------------------------------------------------*/
4609 /* genSkipc                                                        */
4610 /*-----------------------------------------------------------------*/
4611 static void genSkipc(resolvedIfx *rifx)
4612 {
4613   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4614   
4615   if(!rifx)
4616     return;
4617
4618   if(rifx->condition)
4619     emitSKPC;
4620   else
4621     emitSKPNC;
4622
4623   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4624   rifx->generated = 1;
4625 }
4626
4627 /*-----------------------------------------------------------------*/
4628 /* genSkipz2                                                       */
4629 /*-----------------------------------------------------------------*/
4630 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4631 {
4632   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4633   
4634   if(!rifx)
4635     return;
4636
4637   if( (rifx->condition ^ invert_condition) & 1)
4638     emitSKPZ;
4639   else
4640     emitSKPNZ;
4641
4642   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4643   rifx->generated = 1;
4644 }
4645
4646 #if 0
4647 /*-----------------------------------------------------------------*/
4648 /* genSkipz                                                        */
4649 /*-----------------------------------------------------------------*/
4650 static void genSkipz(iCode *ifx, int condition)
4651 {
4652   if(!ifx)
4653     return;
4654
4655   if(condition)
4656     emitSKPNZ;
4657   else
4658     emitSKPZ;
4659
4660   if ( IC_TRUE(ifx) )
4661     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4662   else
4663     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4664
4665   if ( IC_TRUE(ifx) )
4666     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4667   else
4668     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4669
4670 }
4671 #endif
4672
4673 /*-----------------------------------------------------------------*/
4674 /* genSkipCond                                                     */
4675 /*-----------------------------------------------------------------*/
4676 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4677 {
4678   if(!rifx)
4679     return;
4680
4681   if(rifx->condition)
4682     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4683   else
4684     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4685
4686
4687   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4688   rifx->generated = 1;
4689 }
4690
4691 #if 0
4692 /*-----------------------------------------------------------------*/
4693 /* genChkZeroes :- greater or less than comparison                 */
4694 /*     For each byte in a literal that is zero, inclusive or the   */
4695 /*     the corresponding byte in the operand with W                */
4696 /*     returns true if any of the bytes are zero                   */
4697 /*-----------------------------------------------------------------*/
4698 static int genChkZeroes(operand *op, int lit,  int size)
4699 {
4700
4701   int i;
4702   int flag =1;
4703
4704   while(size--) {
4705     i = (lit >> (size*8)) & 0xff;
4706
4707     if(i==0) {
4708       if(flag) 
4709         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4710       else
4711         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4712       flag = 0;
4713     }
4714   }
4715
4716   return (flag==0);
4717 }
4718 #endif
4719
4720 /*-----------------------------------------------------------------*/
4721 /* genCmp :- greater or less than comparison                       */
4722 /*-----------------------------------------------------------------*/
4723 static void genCmp (operand *left,operand *right,
4724                     operand *result, iCode *ifx, int sign)
4725 {
4726   int size; //, offset = 0 ;
4727   unsigned long lit = 0L,i = 0;
4728   resolvedIfx rFalseIfx;
4729   //  resolvedIfx rTrueIfx;
4730   symbol *truelbl;
4731   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4732 /*
4733   if(ifx) {
4734     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4735     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4736   }
4737 */
4738
4739   resolveIfx(&rFalseIfx,ifx);
4740   truelbl  = newiTempLabel(NULL);
4741   size = max(AOP_SIZE(left),AOP_SIZE(right));
4742
4743   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4744
4745 #define _swapp
4746
4747   /* if literal is on the right then swap with left */
4748   if ((AOP_TYPE(right) == AOP_LIT)) {
4749     operand *tmp = right ;
4750     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4751     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4752 #ifdef _swapp
4753
4754     lit = (lit - 1) & mask;
4755     right = left;
4756     left = tmp;
4757     rFalseIfx.condition ^= 1;
4758 #endif
4759
4760   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4761     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4762   }
4763
4764
4765   //if(IC_TRUE(ifx) == NULL)
4766   /* if left & right are bit variables */
4767   if (AOP_TYPE(left) == AOP_CRY &&
4768       AOP_TYPE(right) == AOP_CRY ) {
4769     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4770     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4771   } else {
4772     /* subtract right from left if at the
4773        end the carry flag is set then we know that
4774        left is greater than right */
4775
4776     symbol *lbl  = newiTempLabel(NULL);
4777
4778 #if 0
4779         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4780                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
4781 #endif
4782
4783 #ifndef _swapp
4784     if(AOP_TYPE(right) == AOP_LIT) {
4785
4786       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4787
4788       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4789
4790       /* special cases */
4791
4792       if(lit == 0) {
4793
4794         if(sign != 0) 
4795           genSkipCond(&rFalseIfx,left,size-1,7);
4796         else 
4797           /* no need to compare to 0...*/
4798           /* NOTE: this is a de-generate compare that most certainly 
4799            *       creates some dead code. */
4800           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4801
4802         if(ifx) ifx->generated = 1;
4803         return;
4804
4805       }
4806       size--;
4807
4808       if(size == 0) {
4809         //i = (lit >> (size*8)) & 0xff;
4810         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4811         
4812         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4813
4814         i = ((0-lit) & 0xff);
4815         if(sign) {
4816           if( i == 0x81) { 
4817             /* lit is 0x7f, all signed chars are less than
4818              * this except for 0x7f itself */
4819             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4820             genSkipz2(&rFalseIfx,0);
4821           } else {
4822             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4823             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4824             genSkipc(&rFalseIfx);
4825           }
4826
4827         } else {
4828           if(lit == 1) {
4829             genSkipz2(&rFalseIfx,1);
4830           } else {
4831             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4832             genSkipc(&rFalseIfx);
4833           }
4834         }
4835
4836         if(ifx) ifx->generated = 1;
4837         return;
4838       }
4839
4840       /* chars are out of the way. now do ints and longs */
4841
4842
4843       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4844         
4845       /* special cases */
4846
4847       if(sign) {
4848
4849         if(lit == 0) {
4850           genSkipCond(&rFalseIfx,left,size,7);
4851           if(ifx) ifx->generated = 1;
4852           return;
4853         }
4854
4855         if(lit <0x100) {
4856           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4857
4858           //rFalseIfx.condition ^= 1;
4859           //genSkipCond(&rFalseIfx,left,size,7);
4860           //rFalseIfx.condition ^= 1;
4861
4862           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4863           if(rFalseIfx.condition)
4864             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4865           else
4866             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4867
4868           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4869           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4870           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4871
4872           while(size > 1)
4873             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4874
4875           if(rFalseIfx.condition) {
4876             emitSKPZ;
4877             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4878
4879           } else {
4880             emitSKPNZ;
4881           }
4882
4883           genSkipc(&rFalseIfx);
4884           pic16_emitpLabel(truelbl->key);
4885           if(ifx) ifx->generated = 1;
4886           return;
4887
4888         }
4889
4890         if(size == 1) {
4891
4892           if( (lit & 0xff) == 0) {
4893             /* lower byte is zero */
4894             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4895             i = ((lit >> 8) & 0xff) ^0x80;
4896             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4897             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4898             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4899             genSkipc(&rFalseIfx);
4900
4901
4902             if(ifx) ifx->generated = 1;
4903             return;
4904
4905           }
4906         } else {
4907           /* Special cases for signed longs */
4908           if( (lit & 0xffffff) == 0) {
4909             /* lower byte is zero */
4910             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4911             i = ((lit >> 8*3) & 0xff) ^0x80;
4912             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4913             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4914             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4915             genSkipc(&rFalseIfx);
4916
4917
4918             if(ifx) ifx->generated = 1;
4919             return;
4920
4921           }
4922
4923         }
4924
4925
4926         if(lit & (0x80 << (size*8))) {
4927           /* lit is negative */
4928           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4929
4930           //genSkipCond(&rFalseIfx,left,size,7);
4931
4932           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4933
4934           if(rFalseIfx.condition)
4935             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4936           else
4937             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4938
4939
4940         } else {
4941           /* lit is positive */
4942           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4943           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4944           if(rFalseIfx.condition)
4945             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4946           else
4947             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4948
4949         }
4950
4951         /*
4952           This works, but is only good for ints.
4953           It also requires a "known zero" register.
4954           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4955           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4956           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4957           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4958           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4959           genSkipc(&rFalseIfx);
4960
4961           pic16_emitpLabel(truelbl->key);
4962           if(ifx) ifx->generated = 1;
4963           return;
4964         **/
4965           
4966         /* There are no more special cases, so perform a general compare */
4967   
4968         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4969         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4970
4971         while(size--) {
4972
4973           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4974           emitSKPNZ;
4975           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4976         }
4977         //rFalseIfx.condition ^= 1;
4978         genSkipc(&rFalseIfx);
4979
4980         pic16_emitpLabel(truelbl->key);
4981
4982         if(ifx) ifx->generated = 1;
4983         return;
4984
4985
4986       }
4987
4988
4989       /* sign is out of the way. So now do an unsigned compare */
4990       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4991
4992
4993       /* General case - compare to an unsigned literal on the right.*/
4994
4995       i = (lit >> (size*8)) & 0xff;
4996       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4997       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4998       while(size--) {
4999         i = (lit >> (size*8)) & 0xff;
5000
5001         if(i) {
5002           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5003           emitSKPNZ;
5004           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5005         } else {
5006           /* this byte of the lit is zero, 
5007            *if it's not the last then OR in the variable */
5008           if(size)
5009             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5010         }
5011       }
5012
5013
5014       pic16_emitpLabel(lbl->key);
5015 //      pic16_emitpLabel(truelbl->key);
5016       //if(emitFinalCheck)
5017       genSkipc(&rFalseIfx);
5018       if(sign)
5019         pic16_emitpLabel(truelbl->key);
5020
5021       if(ifx) ifx->generated = 1;
5022       return;
5023
5024
5025     }
5026 #endif  // _swapp
5027
5028     if(AOP_TYPE(left) == AOP_LIT) {
5029       //symbol *lbl = newiTempLabel(NULL);
5030
5031       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5032
5033
5034       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5035
5036       /* Special cases */
5037       if((lit == 0) && (sign == 0)){
5038
5039         size--;
5040         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5041         while(size) 
5042           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5043
5044         genSkipz2(&rFalseIfx,0);
5045         if(ifx) ifx->generated = 1;
5046         return;
5047       }
5048
5049       if(size==1) {
5050         /* Special cases */
5051         lit &= 0xff;
5052         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5053           /* degenerate compare can never be true */
5054           if(rFalseIfx.condition == 0)
5055             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5056
5057           if(ifx) ifx->generated = 1;
5058           return;
5059         }
5060
5061         if(sign) {
5062           /* signed comparisons to a literal byte */
5063
5064           int lp1 = (lit+1) & 0xff;
5065
5066           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5067           switch (lp1) {
5068           case 0:
5069             rFalseIfx.condition ^= 1;
5070             genSkipCond(&rFalseIfx,right,0,7);
5071             break;
5072           case 0x7f:
5073             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5074             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5075             genSkipz2(&rFalseIfx,1);
5076             break;
5077           default:
5078             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5079             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5080             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5081             rFalseIfx.condition ^= 1;
5082             genSkipc(&rFalseIfx);
5083             break;
5084           }
5085         } else {
5086           /* unsigned comparisons to a literal byte */
5087
5088           switch(lit & 0xff ) {
5089           case 0:
5090             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5091             genSkipz2(&rFalseIfx,0);
5092             break;
5093           case 0x7f:
5094             rFalseIfx.condition ^= 1;
5095             genSkipCond(&rFalseIfx,right,0,7);
5096             break;
5097
5098           default:
5099             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5100             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5101             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5102             rFalseIfx.condition ^= 1;
5103             if (AOP_TYPE(result) == AOP_CRY)
5104               genSkipc(&rFalseIfx);
5105             else {
5106               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5107               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5108             }         
5109             break;
5110           }
5111         }
5112
5113         if(ifx) ifx->generated = 1;
5114         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5115                 goto check_carry;
5116         return;
5117
5118       } else {
5119
5120         /* Size is greater than 1 */
5121
5122         if(sign) {
5123           int lp1 = lit+1;
5124
5125           size--;
5126
5127           if(lp1 == 0) {
5128             /* this means lit = 0xffffffff, or -1 */
5129
5130
5131             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5132             rFalseIfx.condition ^= 1;
5133             genSkipCond(&rFalseIfx,right,size,7);
5134             if(ifx) ifx->generated = 1;
5135             return;
5136           }
5137
5138           if(lit == 0) {
5139             int s = size;
5140
5141             if(rFalseIfx.condition) {
5142               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5143               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5144             }
5145
5146             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5147             while(size--)
5148               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5149
5150
5151             emitSKPZ;
5152             if(rFalseIfx.condition) {
5153               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5154               pic16_emitpLabel(truelbl->key);
5155             }else {
5156               rFalseIfx.condition ^= 1;
5157               genSkipCond(&rFalseIfx,right,s,7);
5158             }
5159
5160             if(ifx) ifx->generated = 1;
5161             return;
5162           }
5163
5164           if((size == 1) &&  (0 == (lp1&0xff))) {
5165             /* lower byte of signed word is zero */
5166             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5167             i = ((lp1 >> 8) & 0xff) ^0x80;
5168             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5169             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5170             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5171             rFalseIfx.condition ^= 1;
5172             genSkipc(&rFalseIfx);
5173
5174
5175             if(ifx) ifx->generated = 1;
5176             return;
5177           }
5178
5179           if(lit & (0x80 << (size*8))) {
5180             /* Lit is less than zero */
5181             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5182             //rFalseIfx.condition ^= 1;
5183             //genSkipCond(&rFalseIfx,left,size,7);
5184             //rFalseIfx.condition ^= 1;
5185             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5186             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5187
5188             if(rFalseIfx.condition)
5189               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5190             else
5191               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5192
5193
5194           } else {
5195             /* Lit is greater than or equal to zero */
5196             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5197             //rFalseIfx.condition ^= 1;
5198             //genSkipCond(&rFalseIfx,right,size,7);
5199             //rFalseIfx.condition ^= 1;
5200
5201             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5202             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5203
5204             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5205             if(rFalseIfx.condition)
5206               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5207             else
5208               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5209
5210           }
5211
5212
5213           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5214           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5215
5216           while(size--) {
5217
5218             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5219             emitSKPNZ;
5220             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5221           }
5222           rFalseIfx.condition ^= 1;
5223           //rFalseIfx.condition = 1;
5224           genSkipc(&rFalseIfx);
5225
5226           pic16_emitpLabel(truelbl->key);
5227
5228           if(ifx) ifx->generated = 1;
5229           return;
5230           // end of if (sign)
5231         } else {
5232
5233           /* compare word or long to an unsigned literal on the right.*/
5234
5235
5236           size--;
5237           if(lit < 0xff) {
5238             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5239             switch (lit) {
5240             case 0:
5241               break; /* handled above */
5242 /*
5243             case 0xff:
5244               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5245               while(size--)
5246                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5247               genSkipz2(&rFalseIfx,0);
5248               break;
5249 */
5250             default:
5251               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5252               while(--size)
5253                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5254
5255               emitSKPZ;
5256               if(rFalseIfx.condition)
5257                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5258               else
5259                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5260
5261
5262               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5263               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5264
5265               rFalseIfx.condition ^= 1;
5266               genSkipc(&rFalseIfx);
5267             }
5268
5269             pic16_emitpLabel(truelbl->key);
5270
5271             if(ifx) ifx->generated = 1;
5272             return;
5273           }
5274
5275
5276           lit++;
5277           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5278           i = (lit >> (size*8)) & 0xff;
5279
5280           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5281           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5282
5283           while(size--) {
5284             i = (lit >> (size*8)) & 0xff;
5285
5286             if(i) {
5287               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5288               emitSKPNZ;
5289               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5290             } else {
5291               /* this byte of the lit is zero, 
5292                * if it's not the last then OR in the variable */
5293               if(size)
5294                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5295             }
5296           }
5297
5298
5299           pic16_emitpLabel(lbl->key);
5300
5301           rFalseIfx.condition ^= 1;
5302
5303           genSkipc(&rFalseIfx);
5304         }
5305
5306         if(sign)
5307           pic16_emitpLabel(truelbl->key);
5308         if(ifx) ifx->generated = 1;
5309         return;
5310       }
5311     }
5312     /* Compare two variables */
5313
5314     DEBUGpic16_emitcode(";sign","%d",sign);
5315
5316     size--;
5317     if(sign) {
5318       /* Sigh. thus sucks... */
5319       if(size) {
5320         pCodeOp *pctemp;
5321         
5322         pctemp = pic16_popGetTempReg();
5323         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5324         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5325         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5326         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5327         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5328         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5329         pic16_popReleaseTempReg(pctemp);
5330       } else {
5331         /* Signed char comparison */
5332         /* Special thanks to Nikolai Golovchenko for this snippet */
5333         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5334         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5335         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5336         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5337         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5338         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5339
5340         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5341         genSkipc(&rFalseIfx);
5342           
5343         if(ifx) ifx->generated = 1;
5344         return;
5345       }
5346
5347     } else {
5348
5349       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5350       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5351     }
5352
5353
5354     /* The rest of the bytes of a multi-byte compare */
5355     while (size) {
5356
5357       emitSKPZ;
5358       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5359       size--;
5360
5361       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5362       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5363
5364
5365     }
5366
5367     pic16_emitpLabel(lbl->key);
5368
5369     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5370     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5371         (AOP_TYPE(result) == AOP_REG)) {
5372       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5373       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5374     } else {
5375       genSkipc(&rFalseIfx);
5376     }         
5377     //genSkipc(&rFalseIfx);
5378     if(ifx) ifx->generated = 1;
5379
5380     return;
5381
5382   }
5383
5384 check_carry:
5385   if ((AOP_TYPE(result) != AOP_CRY) 
5386         && AOP_SIZE(result)) {
5387     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5388
5389     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5390
5391     pic16_outBitC(result);
5392   } else {
5393     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5394     /* if the result is used in the next
5395        ifx conditional branch then generate
5396        code a little differently */
5397     if (ifx )
5398       genIfxJump (ifx,"c");
5399     else
5400       pic16_outBitC(result);
5401     /* leave the result in acc */
5402   }
5403
5404 }
5405
5406 /*-----------------------------------------------------------------*/
5407 /* genCmpGt :- greater than comparison                             */
5408 /*-----------------------------------------------------------------*/
5409 static void genCmpGt (iCode *ic, iCode *ifx)
5410 {
5411     operand *left, *right, *result;
5412     sym_link *letype , *retype;
5413     int sign ;
5414
5415     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5416     left = IC_LEFT(ic);
5417     right= IC_RIGHT(ic);
5418     result = IC_RESULT(ic);
5419
5420     letype = getSpec(operandType(left));
5421     retype =getSpec(operandType(right));
5422     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5423     /* assign the amsops */
5424     pic16_aopOp (left,ic,FALSE);
5425     pic16_aopOp (right,ic,FALSE);
5426     pic16_aopOp (result,ic,TRUE);
5427
5428     genCmp(right, left, result, ifx, sign);
5429
5430     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5431     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5432     pic16_freeAsmop(result,NULL,ic,TRUE); 
5433 }
5434
5435 /*-----------------------------------------------------------------*/
5436 /* genCmpLt - less than comparisons                                */
5437 /*-----------------------------------------------------------------*/
5438 static void genCmpLt (iCode *ic, iCode *ifx)
5439 {
5440     operand *left, *right, *result;
5441     sym_link *letype , *retype;
5442     int sign ;
5443
5444     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5445     left = IC_LEFT(ic);
5446     right= IC_RIGHT(ic);
5447     result = IC_RESULT(ic);
5448
5449     letype = getSpec(operandType(left));
5450     retype =getSpec(operandType(right));
5451     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5452
5453     /* assign the amsops */
5454     pic16_aopOp (left,ic,FALSE);
5455     pic16_aopOp (right,ic,FALSE);
5456     pic16_aopOp (result,ic,TRUE);
5457
5458     genCmp(left, right, result, ifx, sign);
5459
5460     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5461     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5462     pic16_freeAsmop(result,NULL,ic,TRUE); 
5463 }
5464
5465 #if 0
5466 // not needed ATM
5467 // FIXME reenable literal optimisation when the pic16 port is stable
5468
5469 /*-----------------------------------------------------------------*/
5470 /* genc16bit2lit - compare a 16 bit value to a literal             */
5471 /*-----------------------------------------------------------------*/
5472 static void genc16bit2lit(operand *op, int lit, int offset)
5473 {
5474   int i;
5475
5476   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
5477   if( (lit&0xff) == 0) 
5478     i=1;
5479   else
5480     i=0;
5481
5482   switch( BYTEofLONG(lit,i)) { 
5483   case 0:
5484     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5485     break;
5486   case 1:
5487     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5488     break;
5489   case 0xff:
5490     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5491     break;
5492   default:
5493     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5494     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5495   }
5496
5497   i ^= 1;
5498
5499   switch( BYTEofLONG(lit,i)) { 
5500   case 0:
5501     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5502     break;
5503   case 1:
5504     emitSKPNZ;
5505     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5506     break;
5507   case 0xff:
5508     emitSKPNZ;
5509     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5510     break;
5511   default:
5512     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5513     emitSKPNZ;
5514     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5515
5516   }
5517
5518 }
5519 #endif
5520
5521 #if 0
5522 // not needed ATM
5523 /*-----------------------------------------------------------------*/
5524 /* gencjneshort - compare and jump if not equal                    */
5525 /*-----------------------------------------------------------------*/
5526 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5527 {
5528   int size = max(AOP_SIZE(left),AOP_SIZE(right));
5529   int offset = 0;
5530   int res_offset = 0;  /* the result may be a different size then left or right */
5531   int res_size = AOP_SIZE(result);
5532   resolvedIfx rIfx;
5533   symbol *lbl, *lbl_done;
5534
5535   unsigned long lit = 0L;
5536   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5537
5538   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5539   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5540   if(result)
5541     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
5542   resolveIfx(&rIfx,ifx);
5543   lbl =  newiTempLabel(NULL);
5544   lbl_done =  newiTempLabel(NULL);
5545
5546
5547   /* if the left side is a literal or 
5548      if the right is in a pointer register and left 
5549      is not */
5550   if ((AOP_TYPE(left) == AOP_LIT) || 
5551       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5552     operand *t = right;
5553     right = left;
5554     left = t;
5555   }
5556   if(AOP_TYPE(right) == AOP_LIT)
5557     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5558
5559   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5560     preserve_result = 1;
5561
5562   if(result && !preserve_result)
5563     {
5564       int i;
5565       for(i = 0; i < AOP_SIZE(result); i++)
5566         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5567     }
5568
5569
5570   /* if the right side is a literal then anything goes */
5571   if (AOP_TYPE(right) == AOP_LIT &&
5572       AOP_TYPE(left) != AOP_DIR ) {
5573     switch(size) {
5574     case 2:
5575       genc16bit2lit(left, lit, 0);
5576       emitSKPZ;
5577       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5578       break;
5579     default:
5580       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5581       while (size--) {
5582         if(lit & 0xff) {
5583           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5584           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5585         } else {
5586           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5587         }
5588
5589         emitSKPZ;
5590         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5591         offset++;
5592         if(res_offset < res_size-1)
5593           res_offset++;
5594         lit >>= 8;
5595       }
5596       break;
5597     }
5598   }
5599
5600   /* if the right side is in a register or in direct space or
5601      if the left is a pointer register & right is not */    
5602   else if (AOP_TYPE(right) == AOP_REG ||
5603            AOP_TYPE(right) == AOP_DIR || 
5604            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5605            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5606     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5607     int lbl_key = lbl->key;
5608
5609     if(result) {
5610       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5611       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5612     }else {
5613       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5614       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5615               __FUNCTION__,__LINE__);
5616       return;
5617     }
5618    
5619 /*     switch(size) { */
5620 /*     case 2: */
5621 /*       genc16bit2lit(left, lit, 0); */
5622 /*       emitSKPNZ; */
5623 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5624 /*       break; */
5625 /*     default: */
5626     while (size--) {
5627       int emit_skip=1;
5628       if((AOP_TYPE(left) == AOP_DIR) && 
5629          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5630
5631         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5632         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5633
5634       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5635             
5636         switch (lit & 0xff) {
5637         case 0:
5638           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5639           break;
5640         case 1:
5641           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5642           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5643           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5644           emit_skip=0;
5645           break;
5646         case 0xff:
5647           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5648           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5649           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5650           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5651           emit_skip=0;
5652           break;
5653         default:
5654           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5655           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5656         }
5657         lit >>= 8;
5658
5659       } else {
5660         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5661       }
5662       if(emit_skip) {
5663         if(AOP_TYPE(result) == AOP_CRY) {
5664           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5665           if(rIfx.condition)
5666             emitSKPNZ;
5667           else
5668             emitSKPZ;
5669           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5670         } else {
5671           /* fix me. probably need to check result size too */
5672           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5673           if(rIfx.condition)
5674             emitSKPZ;
5675           else
5676             emitSKPNZ;
5677           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5678           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5679         }
5680         if(ifx)
5681           ifx->generated=1;
5682       }
5683       emit_skip++;
5684       offset++;
5685       if(res_offset < res_size-1)
5686         res_offset++;
5687     }
5688 /*       break; */
5689 /*     } */
5690   } else if(AOP_TYPE(right) == AOP_REG &&
5691             AOP_TYPE(left) != AOP_DIR){
5692
5693     while(size--) {
5694       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5695       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5696       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5697       if(rIfx.condition)
5698         emitSKPNZ;
5699       else
5700         emitSKPZ;
5701       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5702       offset++;
5703       if(res_offset < res_size-1)
5704         res_offset++;
5705     }
5706       
5707   }else{
5708     /* right is a pointer reg need both a & b */
5709     while(size--) {
5710       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5711       if(strcmp(l,"b"))
5712         pic16_emitcode("mov","b,%s",l);
5713       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5714       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5715       offset++;
5716     }
5717   }
5718
5719   if(result && preserve_result)
5720     {
5721       int i;
5722       for(i = 0; i < AOP_SIZE(result); i++)
5723         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5724     }
5725
5726   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5727
5728   if(result && preserve_result)
5729     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5730
5731   if(!rIfx.condition)
5732     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5733
5734   pic16_emitpLabel(lbl->key);
5735
5736   if(result && preserve_result)
5737     {
5738       int i;
5739       for(i = 0; i < AOP_SIZE(result); i++)
5740         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5741
5742       pic16_emitpLabel(lbl_done->key);
5743    }
5744
5745   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5746
5747   if(ifx)
5748     ifx->generated = 1;
5749 }
5750 #endif
5751
5752 #if 0
5753 /*-----------------------------------------------------------------*/
5754 /* gencjne - compare and jump if not equal                         */
5755 /*-----------------------------------------------------------------*/
5756 static void gencjne(operand *left, operand *right, iCode *ifx)
5757 {
5758     symbol *tlbl  = newiTempLabel(NULL);
5759
5760     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5761     gencjneshort(left, right, lbl);
5762
5763     pic16_emitcode("mov","a,%s",one);
5764     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5765     pic16_emitcode("","%05d_DS_:",lbl->key+100);
5766     pic16_emitcode("clr","a");
5767     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5768
5769     pic16_emitpLabel(lbl->key);
5770     pic16_emitpLabel(tlbl->key);
5771
5772 }
5773 #endif
5774
5775
5776 /*-----------------------------------------------------------------*/
5777 /* is_LitOp - check if operand has to be treated as literal        */
5778 /*-----------------------------------------------------------------*/
5779 static bool is_LitOp(operand *op)
5780 {
5781   return (AOP_TYPE(op) == AOP_LIT)
5782       || ( (AOP_TYPE(op) == AOP_PCODE)
5783           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5784               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));  
5785 }
5786
5787 /*-----------------------------------------------------------------*/
5788 /* is_LitAOp - check if operand has to be treated as literal        */
5789 /*-----------------------------------------------------------------*/
5790 static bool is_LitAOp(asmop *aop)
5791 {
5792   return (aop->type == AOP_LIT)
5793       || ( (aop->type == AOP_PCODE)
5794           && ( (aop->aopu.pcop->type == PO_LITERAL)
5795               || (aop->aopu.pcop->type == PO_IMMEDIATE) ));  
5796 }
5797
5798
5799
5800 /*-----------------------------------------------------------------*/
5801 /* genCmpEq - generates code for equal to                          */
5802 /*-----------------------------------------------------------------*/
5803 static void genCmpEq (iCode *ic, iCode *ifx)
5804 {
5805   operand *left, *right, *result;
5806   symbol *falselbl = newiTempLabel(NULL);
5807   symbol *donelbl = newiTempLabel(NULL);
5808
5809   int preserve_result = 0;
5810   int generate_result = 0;
5811   int i=0;
5812
5813   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5814   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5815   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5816  
5817   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5818   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5819
5820   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5821     {
5822       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5823       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5824       goto release;
5825     }
5826
5827   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5828     {
5829       operand *tmp = right ;
5830       right = left;
5831       left = tmp;
5832     }
5833
5834   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5835     preserve_result = 1;
5836
5837   if(result && AOP_SIZE(result))
5838     generate_result = 1;
5839
5840   if(generate_result && !preserve_result)
5841     {
5842       for(i = 0; i < AOP_SIZE(result); i++)
5843         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5844     }
5845
5846   for(i=0; i < AOP_SIZE(left); i++)
5847     {
5848       if(AOP_TYPE(left) != AOP_ACC)
5849         {
5850           if(is_LitOp(left))
5851             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5852           else
5853             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5854         }
5855       if(is_LitOp(right))
5856         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
5857       else
5858         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
5859
5860       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5861     }
5862
5863   // result == true
5864
5865   if(generate_result && preserve_result)
5866     {
5867       for(i = 0; i < AOP_SIZE(result); i++)
5868         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5869     }
5870
5871   if(generate_result)
5872     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5873
5874   if(generate_result && preserve_result)
5875     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5876
5877   if(ifx && IC_TRUE(ifx))
5878     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5879
5880   if(ifx && IC_FALSE(ifx))
5881     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5882
5883   pic16_emitpLabel(falselbl->key);
5884
5885   // result == false
5886
5887   if(ifx && IC_FALSE(ifx))
5888     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5889
5890   if(generate_result && preserve_result)
5891     {
5892       for(i = 0; i < AOP_SIZE(result); i++)
5893         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5894     }
5895
5896   pic16_emitpLabel(donelbl->key);
5897
5898   if(ifx)
5899     ifx->generated = 1;
5900
5901 release:
5902   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5903   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5904   pic16_freeAsmop(result,NULL,ic,TRUE);
5905
5906 }
5907
5908
5909 #if 0
5910 // old version kept for reference
5911
5912 /*-----------------------------------------------------------------*/
5913 /* genCmpEq - generates code for equal to                          */
5914 /*-----------------------------------------------------------------*/
5915 static void genCmpEq (iCode *ic, iCode *ifx)
5916 {
5917     operand *left, *right, *result;
5918     unsigned long lit = 0L;
5919     int size,offset=0;
5920     symbol *falselbl  = newiTempLabel(NULL);
5921
5922
5923     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5924
5925     if(ifx)
5926       DEBUGpic16_emitcode ("; ifx is non-null","");
5927     else
5928       DEBUGpic16_emitcode ("; ifx is null","");
5929
5930     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5931     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5932     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5933
5934     size = max(AOP_SIZE(left),AOP_SIZE(right));
5935
5936     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5937
5938     /* if literal, literal on the right or 
5939     if the right is in a pointer register and left 
5940     is not */
5941     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
5942         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5943       operand *tmp = right ;
5944       right = left;
5945       left = tmp;
5946     }
5947
5948
5949     if(ifx && !AOP_SIZE(result)){
5950         symbol *tlbl;
5951         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
5952         /* if they are both bit variables */
5953         if (AOP_TYPE(left) == AOP_CRY &&
5954             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5955                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
5956             if(AOP_TYPE(right) == AOP_LIT){
5957                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5958                 if(lit == 0L){
5959                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5960                     pic16_emitcode("cpl","c");
5961                 } else if(lit == 1L) {
5962                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5963                 } else {
5964                     pic16_emitcode("clr","c");
5965                 }
5966                 /* AOP_TYPE(right) == AOP_CRY */
5967             } else {
5968                 symbol *lbl = newiTempLabel(NULL);
5969                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5970                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5971                 pic16_emitcode("cpl","c");
5972                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5973             }
5974             /* if true label then we jump if condition
5975             supplied is true */
5976             tlbl = newiTempLabel(NULL);
5977             if ( IC_TRUE(ifx) ) {
5978                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5979                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5980             } else {
5981                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5982                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5983             }
5984             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5985
5986                 {
5987                 /* left and right are both bit variables, result is carry */
5988                         resolvedIfx rIfx;
5989               
5990                         resolveIfx(&rIfx,ifx);
5991
5992                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5993                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5994                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5995                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5996                         genSkipz2(&rIfx,0);
5997                 }
5998         } else {
5999
6000                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6001
6002                         /* They're not both bit variables. Is the right a literal? */
6003                         if(AOP_TYPE(right) == AOP_LIT) {
6004                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6005             
6006                         switch(size) {
6007
6008                                 case 1:
6009                                         switch(lit & 0xff) {
6010                                                 case 1:
6011                                                                 if ( IC_TRUE(ifx) ) {
6012                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6013                                                                         emitSKPNZ;
6014                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6015                                                                 } else {
6016                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6017                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6018                                                                 }
6019                                                                 break;
6020                                                 case 0xff:
6021                                                                 if ( IC_TRUE(ifx) ) {
6022                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6023                                                                         emitSKPNZ;
6024                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6025                                                                 } else {
6026                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6027                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6028                                                                 }
6029                                                                 break;
6030                                                 default:
6031                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6032                                                                 if(lit)
6033                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6034                                                                 genSkip(ifx,'z');
6035                                         } // switch lit
6036
6037
6038                                         /* end of size == 1 */
6039                                         break;
6040               
6041                                 case 2:
6042                                         genc16bit2lit(left,lit,offset);
6043                                         genSkip(ifx,'z');
6044                                         break;
6045                                         /* end of size == 2 */
6046
6047                                 default:
6048                                         /* size is 4 */
6049                                         if(lit==0) {
6050                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6051                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6052                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6053                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6054                                                 genSkip(ifx,'z');
6055                                         } else {
6056                                                 /* search for patterns that can be optimized */
6057
6058                                                 genc16bit2lit(left,lit,0);
6059                                                 lit >>= 16;
6060                                                 if(lit) {
6061                                                                 if(IC_TRUE(ifx))
6062                                                                 emitSKPZ; // if hi word unequal
6063                                                                 else
6064                                                                 emitSKPNZ; // if hi word equal
6065                                                                 // fail early
6066                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6067                                                         genc16bit2lit(left,lit,2);
6068                                                         genSkip(ifx,'z');
6069                                                 } else {
6070                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6071                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6072                                                         genSkip(ifx,'z');
6073                                                 }
6074                                         }
6075                                                 pic16_emitpLabel(falselbl->key);
6076                                                 break;
6077
6078                         } // switch size
6079           
6080                         ifx->generated = 1;
6081                         goto release ;
6082             
6083
6084           } else if(AOP_TYPE(right) == AOP_CRY ) {
6085             /* we know the left is not a bit, but that the right is */
6086             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6087             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6088                       pic16_popGet(AOP(right),offset));
6089             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6090
6091             /* if the two are equal, then W will be 0 and the Z bit is set
6092              * we could test Z now, or go ahead and check the high order bytes if
6093              * the variable we're comparing is larger than a byte. */
6094
6095             while(--size)
6096               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6097
6098             if ( IC_TRUE(ifx) ) {
6099               emitSKPNZ;
6100               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6101               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6102             } else {
6103               emitSKPZ;
6104               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6105               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6106             }
6107
6108           } else {
6109             /* They're both variables that are larger than bits */
6110             int s = size;
6111
6112             tlbl = newiTempLabel(NULL);
6113
6114             while(size--) {
6115               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6116               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6117
6118               if ( IC_TRUE(ifx) ) {
6119                 if(size) {
6120                   emitSKPZ;
6121                 
6122                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6123
6124                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6125                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6126                 } else {
6127                   emitSKPNZ;
6128
6129                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6130
6131
6132                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6133                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6134                 }
6135               } else {
6136                 emitSKPZ;
6137
6138                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6139
6140                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6141                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6142               }
6143               offset++;
6144             }
6145             if(s>1 && IC_TRUE(ifx)) {
6146               pic16_emitpLabel(tlbl->key);
6147               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
6148             }
6149           }
6150         }
6151         /* mark the icode as generated */
6152         ifx->generated = 1;
6153         goto release ;
6154     }
6155
6156     /* if they are both bit variables */
6157     if (AOP_TYPE(left) == AOP_CRY &&
6158         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6159         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
6160         if(AOP_TYPE(right) == AOP_LIT){
6161             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6162             if(lit == 0L){
6163                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6164                 pic16_emitcode("cpl","c");
6165             } else if(lit == 1L) {
6166                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6167             } else {
6168                 pic16_emitcode("clr","c");
6169             }
6170             /* AOP_TYPE(right) == AOP_CRY */
6171         } else {
6172             symbol *lbl = newiTempLabel(NULL);
6173             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6174             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6175             pic16_emitcode("cpl","c");
6176             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6177         }
6178         /* c = 1 if egal */
6179         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6180             pic16_outBitC(result);
6181             goto release ;
6182         }
6183         if (ifx) {
6184             genIfxJump (ifx,"c");
6185             goto release ;
6186         }
6187         /* if the result is used in an arithmetic operation
6188         then put the result in place */
6189         pic16_outBitC(result);
6190     } else {
6191       
6192       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
6193       gencjne(left,right,result,ifx);
6194 /*
6195       if(ifx) 
6196         gencjne(left,right,newiTempLabel(NULL));
6197       else {
6198         if(IC_TRUE(ifx)->key)
6199           gencjne(left,right,IC_TRUE(ifx)->key);
6200         else
6201           gencjne(left,right,IC_FALSE(ifx)->key);
6202         ifx->generated = 1;
6203         goto release ;
6204       }
6205       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6206         pic16_aopPut(AOP(result),"a",0);
6207         goto release ;
6208       }
6209
6210       if (ifx) {
6211         genIfxJump (ifx,"a");
6212         goto release ;
6213       }
6214 */
6215       /* if the result is used in an arithmetic operation
6216          then put the result in place */
6217 /*
6218       if (AOP_TYPE(result) != AOP_CRY) 
6219         pic16_outAcc(result);
6220 */
6221       /* leave the result in acc */
6222     }
6223
6224 release:
6225     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6226     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6227     pic16_freeAsmop(result,NULL,ic,TRUE);
6228 }
6229 #endif
6230
6231 /*-----------------------------------------------------------------*/
6232 /* ifxForOp - returns the icode containing the ifx for operand     */
6233 /*-----------------------------------------------------------------*/
6234 static iCode *ifxForOp ( operand *op, iCode *ic )
6235 {
6236     /* if true symbol then needs to be assigned */
6237     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6238     if (IS_TRUE_SYMOP(op))
6239         return NULL ;
6240
6241     /* if this has register type condition and
6242     the next instruction is ifx with the same operand
6243     and live to of the operand is upto the ifx only then */
6244     if (ic->next
6245         && ic->next->op == IFX
6246         && IC_COND(ic->next)->key == op->key
6247         && OP_SYMBOL(op)->liveTo <= ic->next->seq
6248         ) {
6249                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6250           return ic->next;
6251     }
6252
6253     if (ic->next &&
6254         ic->next->op == IFX &&
6255         IC_COND(ic->next)->key == op->key) {
6256       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6257       return ic->next;
6258     }
6259
6260     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6261     if (ic->next &&
6262         ic->next->op == IFX)
6263       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6264
6265     if (ic->next &&
6266         ic->next->op == IFX &&
6267         IC_COND(ic->next)->key == op->key) {
6268       DEBUGpic16_emitcode ("; "," key is okay");
6269       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6270                            OP_SYMBOL(op)->liveTo,
6271                            ic->next->seq);
6272     }
6273
6274 #if 0
6275     /* the code below is completely untested
6276      * it just allows ulong2fs.c compile -- VR */
6277          
6278     ic = ic->next;
6279     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6280                                         __FILE__, __FUNCTION__, __LINE__);
6281         
6282     /* if this has register type condition and
6283     the next instruction is ifx with the same operand
6284     and live to of the operand is upto the ifx only then */
6285     if (ic->next &&
6286         ic->next->op == IFX &&
6287         IC_COND(ic->next)->key == op->key &&
6288         OP_SYMBOL(op)->liveTo <= ic->next->seq )
6289         return ic->next;
6290
6291     if (ic->next &&
6292         ic->next->op == IFX &&
6293         IC_COND(ic->next)->key == op->key) {
6294       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6295       return ic->next;
6296     }
6297
6298     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6299                                         __FILE__, __FUNCTION__, __LINE__);
6300
6301 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
6302 #endif
6303
6304     return NULL;
6305 }
6306 /*-----------------------------------------------------------------*/
6307 /* genAndOp - for && operation                                     */
6308 /*-----------------------------------------------------------------*/
6309 static void genAndOp (iCode *ic)
6310 {
6311     operand *left,*right, *result;
6312 /*     symbol *tlbl; */
6313
6314     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6315     /* note here that && operations that are in an
6316     if statement are taken away by backPatchLabels
6317     only those used in arthmetic operations remain */
6318     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6319     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6320     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6321
6322     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6323
6324     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6325     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6326     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6327
6328     /* if both are bit variables */
6329 /*     if (AOP_TYPE(left) == AOP_CRY && */
6330 /*         AOP_TYPE(right) == AOP_CRY ) { */
6331 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6332 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6333 /*         pic16_outBitC(result); */
6334 /*     } else { */
6335 /*         tlbl = newiTempLabel(NULL); */
6336 /*         pic16_toBoolean(left);     */
6337 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6338 /*         pic16_toBoolean(right); */
6339 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6340 /*         pic16_outBitAcc(result); */
6341 /*     } */
6342
6343     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6344     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6345     pic16_freeAsmop(result,NULL,ic,TRUE);
6346 }
6347
6348
6349 /*-----------------------------------------------------------------*/
6350 /* genOrOp - for || operation                                      */
6351 /*-----------------------------------------------------------------*/
6352 /*
6353   tsd pic port -
6354   modified this code, but it doesn't appear to ever get called
6355 */
6356
6357 static void genOrOp (iCode *ic)
6358 {
6359     operand *left,*right, *result;
6360     symbol *tlbl;
6361
6362     /* note here that || operations that are in an
6363     if statement are taken away by backPatchLabels
6364     only those used in arthmetic operations remain */
6365     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6366     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6367     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6368     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6369
6370     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6371
6372     /* if both are bit variables */
6373     if (AOP_TYPE(left) == AOP_CRY &&
6374         AOP_TYPE(right) == AOP_CRY ) {
6375       pic16_emitcode("clrc","");
6376       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6377                AOP(left)->aopu.aop_dir,
6378                AOP(left)->aopu.aop_dir);
6379       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6380                AOP(right)->aopu.aop_dir,
6381                AOP(right)->aopu.aop_dir);
6382       pic16_emitcode("setc","");
6383
6384     } else {
6385         tlbl = newiTempLabel(NULL);
6386         pic16_toBoolean(left);
6387         emitSKPZ;
6388         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
6389         pic16_toBoolean(right);
6390         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6391
6392         pic16_outBitAcc(result);
6393     }
6394
6395     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6396     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6397     pic16_freeAsmop(result,NULL,ic,TRUE);            
6398 }
6399
6400 /*-----------------------------------------------------------------*/
6401 /* isLiteralBit - test if lit == 2^n                               */
6402 /*-----------------------------------------------------------------*/
6403 static int isLiteralBit(unsigned long lit)
6404 {
6405     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6406     0x100L,0x200L,0x400L,0x800L,
6407     0x1000L,0x2000L,0x4000L,0x8000L,
6408     0x10000L,0x20000L,0x40000L,0x80000L,
6409     0x100000L,0x200000L,0x400000L,0x800000L,
6410     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6411     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6412     int idx;
6413     
6414     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6415     for(idx = 0; idx < 32; idx++)
6416         if(lit == pw[idx])
6417             return idx+1;
6418     return 0;
6419 }
6420
6421 /*-----------------------------------------------------------------*/
6422 /* continueIfTrue -                                                */
6423 /*-----------------------------------------------------------------*/
6424 static void continueIfTrue (iCode *ic)
6425 {
6426     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6427     if(IC_TRUE(ic))
6428         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6429     ic->generated = 1;
6430 }
6431
6432 /*-----------------------------------------------------------------*/
6433 /* jmpIfTrue -                                                     */
6434 /*-----------------------------------------------------------------*/
6435 static void jumpIfTrue (iCode *ic)
6436 {
6437     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6438     if(!IC_TRUE(ic))
6439         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6440     ic->generated = 1;
6441 }
6442
6443 /*-----------------------------------------------------------------*/
6444 /* jmpTrueOrFalse -                                                */
6445 /*-----------------------------------------------------------------*/
6446 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6447 {
6448     // ugly but optimized by peephole
6449     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6450     if(IC_TRUE(ic)){
6451         symbol *nlbl = newiTempLabel(NULL);
6452         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
6453         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6454         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6455         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6456     }
6457     else{
6458         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6459         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6460     }
6461     ic->generated = 1;
6462 }
6463
6464 /*-----------------------------------------------------------------*/
6465 /* genAnd  - code for and                                          */
6466 /*-----------------------------------------------------------------*/
6467 static void genAnd (iCode *ic, iCode *ifx)
6468 {
6469   operand *left, *right, *result;
6470   int size, offset=0;  
6471   unsigned long lit = 0L;
6472   int bytelit = 0;
6473   resolvedIfx rIfx;
6474
6475
6476   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6477   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6478   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6479   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6480
6481   resolveIfx(&rIfx,ifx);
6482
6483   /* if left is a literal & right is not then exchange them */
6484   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6485       AOP_NEEDSACC(left)) {
6486     operand *tmp = right ;
6487     right = left;
6488     left = tmp;
6489   }
6490
6491   /* if result = right then exchange them */
6492   if(pic16_sameRegs(AOP(result),AOP(right))){
6493     operand *tmp = right ;
6494     right = left;
6495     left = tmp;
6496   }
6497
6498   /* if right is bit then exchange them */
6499   if (AOP_TYPE(right) == AOP_CRY &&
6500       AOP_TYPE(left) != AOP_CRY){
6501     operand *tmp = right ;
6502     right = left;
6503     left = tmp;
6504   }
6505   if(AOP_TYPE(right) == AOP_LIT)
6506     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6507
6508   size = AOP_SIZE(result);
6509
6510   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6511
6512   // if(bit & yy)
6513   // result = bit & yy;
6514   if (AOP_TYPE(left) == AOP_CRY){
6515     // c = bit & literal;
6516     if(AOP_TYPE(right) == AOP_LIT){
6517       if(lit & 1) {
6518         if(size && pic16_sameRegs(AOP(result),AOP(left)))
6519           // no change
6520           goto release;
6521         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6522       } else {
6523         // bit(result) = 0;
6524         if(size && (AOP_TYPE(result) == AOP_CRY)){
6525           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6526           goto release;
6527         }
6528         if((AOP_TYPE(result) == AOP_CRY) && ifx){
6529           jumpIfTrue(ifx);
6530           goto release;
6531         }
6532         pic16_emitcode("clr","c");
6533       }
6534     } else {
6535       if (AOP_TYPE(right) == AOP_CRY){
6536         // c = bit & bit;
6537         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6538         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6539       } else {
6540         // c = bit & val;
6541         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6542         // c = lsb
6543         pic16_emitcode("rrc","a");
6544         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6545       }
6546     }
6547     // bit = c
6548     // val = c
6549     if(size)
6550       pic16_outBitC(result);
6551     // if(bit & ...)
6552     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6553       genIfxJump(ifx, "c");           
6554     goto release ;
6555   }
6556
6557   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6558   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6559   if((AOP_TYPE(right) == AOP_LIT) &&
6560      (AOP_TYPE(result) == AOP_CRY) &&
6561      (AOP_TYPE(left) != AOP_CRY)){
6562     int posbit = isLiteralBit(lit);
6563     /* left &  2^n */
6564     if(posbit){
6565       posbit--;
6566       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6567       // bit = left & 2^n
6568       if(size)
6569         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6570       // if(left &  2^n)
6571       else{
6572         if(ifx){
6573 /*
6574           if(IC_TRUE(ifx)) {
6575             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6576             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6577           } else {
6578             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6579             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6580           }
6581 */
6582         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
6583         size = AOP_SIZE(left);
6584
6585         {
6586           int bp = posbit, ofs=0;
6587           
6588             while(bp > 7) {
6589               bp -= 8;
6590               ofs++;
6591             }
6592         
6593           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6594                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
6595
6596         }
6597 /*
6598           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6599                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6600 */
6601           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6602           
6603           ifx->generated = 1;
6604         }
6605         goto release;
6606       }
6607     } else {
6608       symbol *tlbl = newiTempLabel(NULL);
6609       int sizel = AOP_SIZE(left);
6610
6611       if(size)
6612         emitSETC;
6613
6614       while(sizel--) {
6615         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
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), offset,FALSE,FALSE),
6621                                                 (posbit-1),0, PO_GPR_REGISTER));
6622
6623               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
6624 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
6625           } else {
6626               if (bytelit == 0xff) {
6627                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
6628                    * a peephole could optimize it out -- VR */
6629                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6630               } else {
6631                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6632                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
6633               }
6634
6635               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
6636                             pic16_popGetLabel(tlbl->key));
6637           }
6638         
6639 #if 0
6640           /* old code, left here for reference -- VR 09/2004 */
6641           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6642           // byte ==  2^n ?
6643           if((posbit = isLiteralBit(bytelit)) != 0)
6644             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6645           else{
6646             if(bytelit != 0x0FFL)
6647               pic16_emitcode("anl","a,%s",
6648                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6649             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6650           }
6651 #endif
6652         }
6653         offset++;
6654       }
6655       // bit = left & literal
6656       if(size) {
6657         emitCLRC;
6658         pic16_emitpLabel(tlbl->key);
6659       }
6660       // if(left & literal)
6661       else {
6662         if(ifx) {
6663           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
6664           pic16_emitpLabel(tlbl->key);
6665           ifx->generated = 1;
6666         }
6667         goto release;
6668       }
6669     }
6670
6671     pic16_outBitC(result);
6672     goto release ;
6673   }
6674
6675   /* if left is same as result */
6676   if(pic16_sameRegs(AOP(result),AOP(left))){
6677     int know_W = -1;
6678     for(;size--; offset++,lit>>=8) {
6679       if(AOP_TYPE(right) == AOP_LIT){
6680         switch(lit & 0xff) {
6681         case 0x00:
6682           /*  and'ing with 0 has clears the result */
6683 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6684           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6685           break;
6686         case 0xff:
6687           /* and'ing with 0xff is a nop when the result and left are the same */
6688           break;
6689
6690         default:
6691           {
6692             int p = my_powof2( (~lit) & 0xff );
6693             if(p>=0) {
6694               /* only one bit is set in the literal, so use a bcf instruction */
6695 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6696               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6697
6698             } else {
6699               pic16_emitcode("movlw","0x%x", (lit & 0xff));
6700               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6701               if(know_W != (lit&0xff))
6702                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6703               know_W = lit &0xff;
6704               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6705             }
6706           }    
6707         }
6708       } else {
6709         if (AOP_TYPE(left) == AOP_ACC) {
6710           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6711         } else {                    
6712           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6713           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6714
6715         }
6716       }
6717     }
6718
6719   } else {
6720     // left & result in different registers
6721     if(AOP_TYPE(result) == AOP_CRY){
6722       // result = bit
6723       // if(size), result in bit
6724       // if(!size && ifx), conditional oper: if(left & right)
6725       symbol *tlbl = newiTempLabel(NULL);
6726       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6727       if(size)
6728         pic16_emitcode("setb","c");
6729       while(sizer--){
6730         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6731         pic16_emitcode("anl","a,%s",
6732                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6733         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6734         offset++;
6735       }
6736       if(size){
6737         CLRC;
6738         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6739         pic16_outBitC(result);
6740       } else if(ifx)
6741         jmpTrueOrFalse(ifx, tlbl);
6742     } else {
6743       for(;(size--);offset++) {
6744         // normal case
6745         // result = left & right
6746         if(AOP_TYPE(right) == AOP_LIT){
6747           int t = (lit >> (offset*8)) & 0x0FFL;
6748           switch(t) { 
6749           case 0x00:
6750             pic16_emitcode("clrf","%s",
6751                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6752             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6753             break;
6754           case 0xff:
6755             pic16_emitcode("movf","%s,w",
6756                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6757             pic16_emitcode("movwf","%s",
6758                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6759             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6760             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6761             break;
6762           default:
6763             pic16_emitcode("movlw","0x%x",t);
6764             pic16_emitcode("andwf","%s,w",
6765                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6766             pic16_emitcode("movwf","%s",
6767                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6768               
6769             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6770             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6771             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6772           }
6773           continue;
6774         }
6775
6776         if (AOP_TYPE(left) == AOP_ACC) {
6777           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6778           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6779         } else {
6780           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6781           pic16_emitcode("andwf","%s,w",
6782                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6783           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6784           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6785         }
6786         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6787         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6788       }
6789     }
6790   }
6791
6792   release :
6793     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6794   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6795   pic16_freeAsmop(result,NULL,ic,TRUE);     
6796 }
6797
6798 /*-----------------------------------------------------------------*/
6799 /* genOr  - code for or                                            */
6800 /*-----------------------------------------------------------------*/
6801 static void genOr (iCode *ic, iCode *ifx)
6802 {
6803     operand *left, *right, *result;
6804     int size, offset=0;
6805     unsigned long lit = 0L;
6806
6807     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6808
6809     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6810     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6811     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6812
6813     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6814
6815     /* if left is a literal & right is not then exchange them */
6816     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6817         AOP_NEEDSACC(left)) {
6818         operand *tmp = right ;
6819         right = left;
6820         left = tmp;
6821     }
6822
6823     /* if result = right then exchange them */
6824     if(pic16_sameRegs(AOP(result),AOP(right))){
6825         operand *tmp = right ;
6826         right = left;
6827         left = tmp;
6828     }
6829
6830     /* if right is bit then exchange them */
6831     if (AOP_TYPE(right) == AOP_CRY &&
6832         AOP_TYPE(left) != AOP_CRY){
6833         operand *tmp = right ;
6834         right = left;
6835         left = tmp;
6836     }
6837
6838     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6839
6840     if(AOP_TYPE(right) == AOP_LIT)
6841         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6842
6843     size = AOP_SIZE(result);
6844
6845     // if(bit | yy)
6846     // xx = bit | yy;
6847     if (AOP_TYPE(left) == AOP_CRY){
6848         if(AOP_TYPE(right) == AOP_LIT){
6849             // c = bit & literal;
6850             if(lit){
6851                 // lit != 0 => result = 1
6852                 if(AOP_TYPE(result) == AOP_CRY){
6853                   if(size)
6854                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6855                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6856                   //     AOP(result)->aopu.aop_dir,
6857                   //     AOP(result)->aopu.aop_dir);
6858                     else if(ifx)
6859                         continueIfTrue(ifx);
6860                     goto release;
6861                 }
6862             } else {
6863                 // lit == 0 => result = left
6864                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6865                     goto release;
6866                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6867             }
6868         } else {
6869             if (AOP_TYPE(right) == AOP_CRY){
6870               if(pic16_sameRegs(AOP(result),AOP(left))){
6871                 // c = bit | bit;
6872                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6873                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6874                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6875
6876                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6877                          AOP(result)->aopu.aop_dir,
6878                          AOP(result)->aopu.aop_dir);
6879                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6880                          AOP(right)->aopu.aop_dir,
6881                          AOP(right)->aopu.aop_dir);
6882                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6883                          AOP(result)->aopu.aop_dir,
6884                          AOP(result)->aopu.aop_dir);
6885               } else {
6886                 if( AOP_TYPE(result) == AOP_ACC) {
6887                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6888                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6889                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6890                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6891
6892                 } else {
6893
6894                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6895                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6896                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6897                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6898
6899                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6900                                  AOP(result)->aopu.aop_dir,
6901                                  AOP(result)->aopu.aop_dir);
6902                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6903                                  AOP(right)->aopu.aop_dir,
6904                                  AOP(right)->aopu.aop_dir);
6905                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6906                                  AOP(left)->aopu.aop_dir,
6907                                  AOP(left)->aopu.aop_dir);
6908                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6909                                  AOP(result)->aopu.aop_dir,
6910                                  AOP(result)->aopu.aop_dir);
6911                 }
6912               }
6913             } else {
6914                 // c = bit | val;
6915                 symbol *tlbl = newiTempLabel(NULL);
6916                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6917
6918
6919                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6920                 if( AOP_TYPE(right) == AOP_ACC) {
6921                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6922                   emitSKPNZ;
6923                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6924                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6925                 }
6926
6927
6928
6929                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6930                     pic16_emitcode(";XXX setb","c");
6931                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6932                          AOP(left)->aopu.aop_dir,tlbl->key+100);
6933                 pic16_toBoolean(right);
6934                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6935                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6936                     jmpTrueOrFalse(ifx, tlbl);
6937                     goto release;
6938                 } else {
6939                     CLRC;
6940                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6941                 }
6942             }
6943         }
6944         // bit = c
6945         // val = c
6946         if(size)
6947             pic16_outBitC(result);
6948         // if(bit | ...)
6949         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6950             genIfxJump(ifx, "c");           
6951         goto release ;
6952     }
6953
6954     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6955     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6956     if((AOP_TYPE(right) == AOP_LIT) &&
6957        (AOP_TYPE(result) == AOP_CRY) &&
6958        (AOP_TYPE(left) != AOP_CRY)){
6959         if(lit){
6960           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6961             // result = 1
6962             if(size)
6963                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6964             else 
6965                 continueIfTrue(ifx);
6966             goto release;
6967         } else {
6968           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6969             // lit = 0, result = boolean(left)
6970             if(size)
6971                 pic16_emitcode(";XXX setb","c");
6972             pic16_toBoolean(right);
6973             if(size){
6974                 symbol *tlbl = newiTempLabel(NULL);
6975                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6976                 CLRC;
6977                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6978             } else {
6979                 genIfxJump (ifx,"a");
6980                 goto release;
6981             }
6982         }
6983         pic16_outBitC(result);
6984         goto release ;
6985     }
6986
6987     /* if left is same as result */
6988     if(pic16_sameRegs(AOP(result),AOP(left))){
6989       int know_W = -1;
6990       for(;size--; offset++,lit>>=8) {
6991         if(AOP_TYPE(right) == AOP_LIT){
6992           if((lit & 0xff) == 0)
6993             /*  or'ing with 0 has no effect */
6994             continue;
6995           else {
6996             int p = my_powof2(lit & 0xff);
6997             if(p>=0) {
6998               /* only one bit is set in the literal, so use a bsf instruction */
6999               pic16_emitpcode(POC_BSF,
7000                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7001             } else {
7002               if(know_W != (lit & 0xff))
7003                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7004               know_W = lit & 0xff;
7005               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7006             }
7007                     
7008           }
7009         } else {
7010           if (AOP_TYPE(left) == AOP_ACC) {
7011             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7012             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7013           } else {                  
7014             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7015             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7016
7017             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7018             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7019
7020           }
7021         }
7022       }
7023     } else {
7024         // left & result in different registers
7025         if(AOP_TYPE(result) == AOP_CRY){
7026             // result = bit
7027             // if(size), result in bit
7028             // if(!size && ifx), conditional oper: if(left | right)
7029             symbol *tlbl = newiTempLabel(NULL);
7030             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7031             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7032
7033
7034             if(size)
7035                 pic16_emitcode(";XXX setb","c");
7036             while(sizer--){
7037                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7038                 pic16_emitcode(";XXX orl","a,%s",
7039                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7040                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7041                 offset++;
7042             }
7043             if(size){
7044                 CLRC;
7045                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7046                 pic16_outBitC(result);
7047             } else if(ifx)
7048                 jmpTrueOrFalse(ifx, tlbl);
7049         } else for(;(size--);offset++){
7050           // normal case
7051           // result = left & right
7052           if(AOP_TYPE(right) == AOP_LIT){
7053             int t = (lit >> (offset*8)) & 0x0FFL;
7054             switch(t) { 
7055             case 0x00:
7056               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7057               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7058
7059               pic16_emitcode("movf","%s,w",
7060                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7061               pic16_emitcode("movwf","%s",
7062                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7063               break;
7064             default:
7065               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7066               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7067               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7068
7069               pic16_emitcode("movlw","0x%x",t);
7070               pic16_emitcode("iorwf","%s,w",
7071                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7072               pic16_emitcode("movwf","%s",
7073                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7074               
7075             }
7076             continue;
7077           }
7078
7079           // faster than result <- left, anl result,right
7080           // and better if result is SFR
7081           if (AOP_TYPE(left) == AOP_ACC) {
7082             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7083             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7084           } else {
7085             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7086             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7087
7088             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7089             pic16_emitcode("iorwf","%s,w",
7090                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7091           }
7092           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7093           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7094         }
7095     }
7096
7097 release :
7098     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7099     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7100     pic16_freeAsmop(result,NULL,ic,TRUE);     
7101 }
7102
7103 /*-----------------------------------------------------------------*/
7104 /* genXor - code for xclusive or                                   */
7105 /*-----------------------------------------------------------------*/
7106 static void genXor (iCode *ic, iCode *ifx)
7107 {
7108   operand *left, *right, *result;
7109   int size, offset=0;
7110   unsigned long lit = 0L;
7111
7112   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7113
7114   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7115   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7116   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7117
7118   /* if left is a literal & right is not ||
7119      if left needs acc & right does not */
7120   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7121       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7122     operand *tmp = right ;
7123     right = left;
7124     left = tmp;
7125   }
7126
7127   /* if result = right then exchange them */
7128   if(pic16_sameRegs(AOP(result),AOP(right))){
7129     operand *tmp = right ;
7130     right = left;
7131     left = tmp;
7132   }
7133
7134   /* if right is bit then exchange them */
7135   if (AOP_TYPE(right) == AOP_CRY &&
7136       AOP_TYPE(left) != AOP_CRY){
7137     operand *tmp = right ;
7138     right = left;
7139     left = tmp;
7140   }
7141   if(AOP_TYPE(right) == AOP_LIT)
7142     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7143
7144   size = AOP_SIZE(result);
7145
7146   // if(bit ^ yy)
7147   // xx = bit ^ yy;
7148   if (AOP_TYPE(left) == AOP_CRY){
7149     if(AOP_TYPE(right) == AOP_LIT){
7150       // c = bit & literal;
7151       if(lit>>1){
7152         // lit>>1  != 0 => result = 1
7153         if(AOP_TYPE(result) == AOP_CRY){
7154           if(size)
7155             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
7156             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7157           else if(ifx)
7158             continueIfTrue(ifx);
7159           goto release;
7160         }
7161         pic16_emitcode("setb","c");
7162       } else{
7163         // lit == (0 or 1)
7164         if(lit == 0){
7165           // lit == 0, result = left
7166           if(size && pic16_sameRegs(AOP(result),AOP(left)))
7167             goto release;
7168           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7169         } else{
7170           // lit == 1, result = not(left)
7171           if(size && pic16_sameRegs(AOP(result),AOP(left))){
7172             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
7173             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
7174             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7175             goto release;
7176           } else {
7177             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7178             pic16_emitcode("cpl","c");
7179           }
7180         }
7181       }
7182
7183     } else {
7184       // right != literal
7185       symbol *tlbl = newiTempLabel(NULL);
7186       if (AOP_TYPE(right) == AOP_CRY){
7187         // c = bit ^ bit;
7188         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7189       }
7190       else{
7191         int sizer = AOP_SIZE(right);
7192         // c = bit ^ val
7193         // if val>>1 != 0, result = 1
7194         pic16_emitcode("setb","c");
7195         while(sizer){
7196           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
7197           if(sizer == 1)
7198             // test the msb of the lsb
7199             pic16_emitcode("anl","a,#0xfe");
7200           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7201           sizer--;
7202         }
7203         // val = (0,1)
7204         pic16_emitcode("rrc","a");
7205       }
7206       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
7207       pic16_emitcode("cpl","c");
7208       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
7209     }
7210     // bit = c
7211     // val = c
7212     if(size)
7213       pic16_outBitC(result);
7214     // if(bit | ...)
7215     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7216       genIfxJump(ifx, "c");           
7217     goto release ;
7218   }
7219
7220   if(pic16_sameRegs(AOP(result),AOP(left))){
7221     /* if left is same as result */
7222     for(;size--; offset++) {
7223       if(AOP_TYPE(right) == AOP_LIT){
7224         int t  = (lit >> (offset*8)) & 0x0FFL;
7225         if(t == 0x00L)
7226           continue;
7227         else
7228           if (IS_AOP_PREG(left)) {
7229             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7230             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7231             pic16_aopPut(AOP(result),"a",offset);
7232           } else {
7233             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7234             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7235             pic16_emitcode("xrl","%s,%s",
7236                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7237                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7238           }
7239       } else {
7240         if (AOP_TYPE(left) == AOP_ACC)
7241           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7242         else {
7243           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7244           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7245 /*
7246           if (IS_AOP_PREG(left)) {
7247             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7248             pic16_aopPut(AOP(result),"a",offset);
7249           } else
7250             pic16_emitcode("xrl","%s,a",
7251                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7252 */
7253         }
7254       }
7255     }
7256   } else {
7257     // left & result in different registers
7258     if(AOP_TYPE(result) == AOP_CRY){
7259       // result = bit
7260       // if(size), result in bit
7261       // if(!size && ifx), conditional oper: if(left ^ right)
7262       symbol *tlbl = newiTempLabel(NULL);
7263       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7264       if(size)
7265         pic16_emitcode("setb","c");
7266       while(sizer--){
7267         if((AOP_TYPE(right) == AOP_LIT) &&
7268            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7269           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7270         } else {
7271           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7272           pic16_emitcode("xrl","a,%s",
7273                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7274         }
7275         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7276         offset++;
7277       }
7278       if(size){
7279         CLRC;
7280         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7281         pic16_outBitC(result);
7282       } else if(ifx)
7283         jmpTrueOrFalse(ifx, tlbl);
7284     } else for(;(size--);offset++){
7285       // normal case
7286       // result = left & right
7287       if(AOP_TYPE(right) == AOP_LIT){
7288         int t = (lit >> (offset*8)) & 0x0FFL;
7289         switch(t) { 
7290         case 0x00:
7291           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7292           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7293           pic16_emitcode("movf","%s,w",
7294                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7295           pic16_emitcode("movwf","%s",
7296                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7297           break;
7298         case 0xff:
7299           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7300           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7301           pic16_emitcode("comf","%s,w",
7302                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7303           pic16_emitcode("movwf","%s",
7304                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7305           break;
7306         default:
7307           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7308           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7309           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7310           pic16_emitcode("movlw","0x%x",t);
7311           pic16_emitcode("xorwf","%s,w",
7312                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7313           pic16_emitcode("movwf","%s",
7314                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7315
7316         }
7317         continue;
7318       }
7319
7320       // faster than result <- left, anl result,right
7321       // and better if result is SFR
7322       if (AOP_TYPE(left) == AOP_ACC) {
7323         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7324         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7325       } else {
7326         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7327         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7328         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7329         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7330       }
7331       if ( AOP_TYPE(result) != AOP_ACC){
7332         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7333         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7334       }
7335     }
7336   }
7337
7338   release :
7339     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7340   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7341   pic16_freeAsmop(result,NULL,ic,TRUE);     
7342 }
7343
7344 /*-----------------------------------------------------------------*/
7345 /* genInline - write the inline code out                           */
7346 /*-----------------------------------------------------------------*/
7347 static void genInline (iCode *ic)
7348 {
7349   char *buffer, *bp, *bp1;
7350     
7351         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7352
7353         _G.inLine += (!options.asmpeep);
7354
7355         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7356         strcpy(buffer,IC_INLINE(ic));
7357
7358 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7359
7360         /* emit each line as a code */
7361         while (*bp) {
7362                 if (*bp == '\n') {
7363                         *bp++ = '\0';
7364
7365                         if(*bp1)
7366                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7367                         bp1 = bp;
7368                 } else {
7369                         if (*bp == ':') {
7370                                 bp++;
7371                                 *bp = '\0';
7372                                 bp++;
7373
7374                                 /* print label, use this special format with NULL directive
7375                                  * to denote that the argument should not be indented with tab */
7376                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7377                                 bp1 = bp;
7378                         } else
7379                                 bp++;
7380                 }
7381         }
7382
7383         if ((bp1 != bp) && *bp1)
7384                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7385
7386
7387     Safe_free(buffer);
7388
7389     _G.inLine -= (!options.asmpeep);
7390 }
7391
7392 /*-----------------------------------------------------------------*/
7393 /* genRRC - rotate right with carry                                */
7394 /*-----------------------------------------------------------------*/
7395 static void genRRC (iCode *ic)
7396 {
7397   operand *left , *result ;
7398   int size, offset = 0, same;
7399
7400   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7401
7402   /* rotate right with carry */
7403   left = IC_LEFT(ic);
7404   result=IC_RESULT(ic);
7405   pic16_aopOp (left,ic,FALSE);
7406   pic16_aopOp (result,ic,FALSE);
7407
7408   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7409
7410   same = pic16_sameRegs(AOP(result),AOP(left));
7411
7412   size = AOP_SIZE(result);    
7413
7414   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7415
7416   /* get the lsb and put it into the carry */
7417   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7418
7419   offset = 0 ;
7420
7421   while(size--) {
7422
7423     if(same) {
7424       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7425     } else {
7426       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7427       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7428     }
7429
7430     offset++;
7431   }
7432
7433   pic16_freeAsmop(left,NULL,ic,TRUE);
7434   pic16_freeAsmop(result,NULL,ic,TRUE);
7435 }
7436
7437 /*-----------------------------------------------------------------*/
7438 /* genRLC - generate code for rotate left with carry               */
7439 /*-----------------------------------------------------------------*/
7440 static void genRLC (iCode *ic)
7441 {    
7442   operand *left , *result ;
7443   int size, offset = 0;
7444   int same;
7445
7446   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7447   /* rotate right with carry */
7448   left = IC_LEFT(ic);
7449   result=IC_RESULT(ic);
7450   pic16_aopOp (left,ic,FALSE);
7451   pic16_aopOp (result,ic,FALSE);
7452
7453   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7454
7455   same = pic16_sameRegs(AOP(result),AOP(left));
7456
7457   /* move it to the result */
7458   size = AOP_SIZE(result);    
7459
7460   /* get the msb and put it into the carry */
7461   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7462
7463   offset = 0 ;
7464
7465   while(size--) {
7466
7467     if(same) {
7468       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7469     } else {
7470       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7471       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7472     }
7473
7474     offset++;
7475   }
7476
7477
7478   pic16_freeAsmop(left,NULL,ic,TRUE);
7479   pic16_freeAsmop(result,NULL,ic,TRUE);
7480 }
7481
7482
7483 /* gpasm can get the highest order bit with HIGH/UPPER
7484  * so the following probably is not needed -- VR */
7485  
7486 /*-----------------------------------------------------------------*/
7487 /* genGetHbit - generates code get highest order bit               */
7488 /*-----------------------------------------------------------------*/
7489 static void genGetHbit (iCode *ic)
7490 {
7491     operand *left, *result;
7492     left = IC_LEFT(ic);
7493     result=IC_RESULT(ic);
7494     pic16_aopOp (left,ic,FALSE);
7495     pic16_aopOp (result,ic,FALSE);
7496
7497     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7498     /* get the highest order byte into a */
7499     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7500     if(AOP_TYPE(result) == AOP_CRY){
7501         pic16_emitcode("rlc","a");
7502         pic16_outBitC(result);
7503     }
7504     else{
7505         pic16_emitcode("rl","a");
7506         pic16_emitcode("anl","a,#0x01");
7507         pic16_outAcc(result);
7508     }
7509
7510
7511     pic16_freeAsmop(left,NULL,ic,TRUE);
7512     pic16_freeAsmop(result,NULL,ic,TRUE);
7513 }
7514
7515 #if 0
7516 /*-----------------------------------------------------------------*/
7517 /* AccRol - rotate left accumulator by known count                 */
7518 /*-----------------------------------------------------------------*/
7519 static void AccRol (int shCount)
7520 {
7521     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7522     shCount &= 0x0007;              // shCount : 0..7
7523     switch(shCount){
7524         case 0 :
7525             break;
7526         case 1 :
7527             pic16_emitcode("rl","a");
7528             break;
7529         case 2 :
7530             pic16_emitcode("rl","a");
7531             pic16_emitcode("rl","a");
7532             break;
7533         case 3 :
7534             pic16_emitcode("swap","a");
7535             pic16_emitcode("rr","a");
7536             break;
7537         case 4 :
7538             pic16_emitcode("swap","a");
7539             break;
7540         case 5 :
7541             pic16_emitcode("swap","a");
7542             pic16_emitcode("rl","a");
7543             break;
7544         case 6 :
7545             pic16_emitcode("rr","a");
7546             pic16_emitcode("rr","a");
7547             break;
7548         case 7 :
7549             pic16_emitcode("rr","a");
7550             break;
7551     }
7552 }
7553 #endif
7554
7555 /*-----------------------------------------------------------------*/
7556 /* AccLsh - left shift accumulator by known count                  */
7557 /*-----------------------------------------------------------------*/
7558 static void AccLsh (int shCount)
7559 {
7560         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7561         switch(shCount){
7562                 case 0 :
7563                         return;
7564                         break;
7565                 case 1 :
7566                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7567                         break;
7568                 case 2 :
7569                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7570                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7571                         break;
7572                 case 3 :
7573                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7574                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7575                         break;
7576                 case 4 :
7577                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7578                         break;
7579                 case 5 :
7580                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7581                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7582                         break;
7583                 case 6 :
7584                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7585                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7586                         break;
7587                 case 7 :
7588                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7589                         break;
7590         }
7591
7592         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7593 }
7594
7595 /*-----------------------------------------------------------------*/
7596 /* AccRsh - right shift accumulator by known count                 */
7597 /*-----------------------------------------------------------------*/
7598 static void AccRsh (int shCount, int andmask)
7599 {
7600         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7601         switch(shCount){
7602                 case 0 :
7603                         return; break;
7604                 case 1 :
7605                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7606 //                      andmask = 0;    /* no need */
7607                         break;
7608                 case 2 :
7609                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7610                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7611 //                      andmask = 0;    /* no need */
7612                         break;
7613                 case 3 :
7614                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7615                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7616                         break;
7617                 case 4 :
7618                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7619                         break;
7620                 case 5 :
7621                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7622                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7623                         break;
7624                 case 6 :
7625                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7626                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7627                         break;
7628                 case 7 :
7629                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7630                         break;
7631         }
7632         
7633         if(andmask)
7634                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7635         else
7636                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7637 }
7638
7639 #if 0
7640 /*-----------------------------------------------------------------*/
7641 /* AccSRsh - signed right shift accumulator by known count                 */
7642 /*-----------------------------------------------------------------*/
7643 static void AccSRsh (int shCount)
7644 {
7645     symbol *tlbl ;
7646     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7647     if(shCount != 0){
7648         if(shCount == 1){
7649             pic16_emitcode("mov","c,acc.7");
7650             pic16_emitcode("rrc","a");
7651         } else if(shCount == 2){
7652             pic16_emitcode("mov","c,acc.7");
7653             pic16_emitcode("rrc","a");
7654             pic16_emitcode("mov","c,acc.7");
7655             pic16_emitcode("rrc","a");
7656         } else {
7657             tlbl = newiTempLabel(NULL);
7658             /* rotate right accumulator */
7659             AccRol(8 - shCount);
7660             /* and kill the higher order bits */
7661             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7662             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7663             pic16_emitcode("orl","a,#0x%02x",
7664                      (unsigned char)~SRMask[shCount]);
7665             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7666         }
7667     }
7668 }
7669 #endif
7670 /*-----------------------------------------------------------------*/
7671 /* shiftR1Left2Result - shift right one byte from left to result   */
7672 /*-----------------------------------------------------------------*/
7673 static void shiftR1Left2ResultSigned (operand *left, int offl,
7674                                 operand *result, int offr,
7675                                 int shCount)
7676 {
7677   int same;
7678
7679   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7680
7681   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7682
7683   switch(shCount) {
7684   case 1:
7685     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7686     if(same) 
7687       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7688     else {
7689       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7690       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7691     }
7692
7693     break;
7694   case 2:
7695
7696     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7697     if(same) 
7698       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7699     else {
7700       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7701       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7702     }
7703     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7704     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7705
7706     break;
7707
7708   case 3:
7709     if(same)
7710       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7711     else {
7712       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7713       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7714     }
7715
7716     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7717     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7718     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7719
7720     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7721     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7722
7723     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7724     break;
7725
7726   case 4:
7727     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7728     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
7729     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7730     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
7731     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7732     break;
7733   case 5:
7734     if(same) {
7735       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
7736     } else {
7737       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
7738       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7739     }
7740     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
7741     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
7742     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7743     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
7744     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7745     break;
7746
7747   case 6:
7748     if(same) {
7749       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7750       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7751       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7752       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7753       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7754       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7755     } else {
7756       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7757       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7758       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7759       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7760       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7761     }
7762     break;
7763
7764   case 7:
7765     if(same) {
7766       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7767       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7768       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7769       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7770     } else {
7771       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7772       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7773       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7774     }
7775
7776   default:
7777     break;
7778   }
7779 }
7780
7781 /*-----------------------------------------------------------------*/
7782 /* shiftR1Left2Result - shift right one byte from left to result   */
7783 /*-----------------------------------------------------------------*/
7784 static void shiftR1Left2Result (operand *left, int offl,
7785                                 operand *result, int offr,
7786                                 int shCount, int sign)
7787 {
7788   int same;
7789
7790   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7791
7792   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7793
7794   /* Copy the msb into the carry if signed. */
7795   if(sign) {
7796     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7797     return;
7798   }
7799
7800
7801
7802   switch(shCount) {
7803   case 1:
7804     emitCLRC;
7805     if(same) 
7806       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7807     else {
7808       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7809       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7810     }
7811     break;
7812   case 2:
7813     emitCLRC;
7814     if(same) {
7815       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7816     } else {
7817       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7818       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7819     }
7820     emitCLRC;
7821     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7822
7823     break;
7824   case 3:
7825     if(same)
7826       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7827     else {
7828       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7829       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7830     }
7831
7832     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7833     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7834     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7835     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7836     break;
7837       
7838   case 4:
7839     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7840     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7841     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7842     break;
7843
7844   case 5:
7845     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7846     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7847     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7848     emitCLRC;
7849     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7850
7851     break;
7852   case 6:
7853
7854     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
7855     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7856     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7857     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7858     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7859     break;
7860
7861   case 7:
7862
7863     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7864     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7865     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7866
7867     break;
7868
7869   default:
7870     break;
7871   }
7872 }
7873
7874 /*-----------------------------------------------------------------*/
7875 /* shiftL1Left2Result - shift left one byte from left to result    */
7876 /*-----------------------------------------------------------------*/
7877 static void shiftL1Left2Result (operand *left, int offl,
7878                                 operand *result, int offr, int shCount)
7879 {
7880   int same;
7881
7882   //    char *l;
7883   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7884
7885   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7886   DEBUGpic16_emitcode ("; ***","same =  %d",same);
7887     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7888     //    MOVA(l);
7889     /* shift left accumulator */
7890     //AccLsh(shCount); // don't comment out just yet...
7891   //    pic16_aopPut(AOP(result),"a",offr);
7892
7893   switch(shCount) {
7894   case 1:
7895     /* Shift left 1 bit position */
7896     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7897     if(same) {
7898       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7899     } else {
7900       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7901       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7902     }
7903     break;
7904   case 2:
7905     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7906     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7907     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7908     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7909     break;
7910   case 3:
7911     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7912     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7913     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7914     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7915     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7916     break;
7917   case 4:
7918     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7919     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7920     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7921     break;
7922   case 5:
7923     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7924     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7925     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7926     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7927     break;
7928   case 6:
7929     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7930     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7931     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7932     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7933     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7934     break;
7935   case 7:
7936     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7937     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7938     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7939     break;
7940
7941   default:
7942     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7943   }
7944
7945 }
7946
7947 /*-----------------------------------------------------------------*/
7948 /* movLeft2Result - move byte from left to result                  */
7949 /*-----------------------------------------------------------------*/
7950 static void movLeft2Result (operand *left, int offl,
7951                             operand *result, int offr)
7952 {
7953   char *l;
7954   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7955   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7956     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7957
7958     if (*l == '@' && (IS_AOP_PREG(result))) {
7959       pic16_emitcode("mov","a,%s",l);
7960       pic16_aopPut(AOP(result),"a",offr);
7961     } else {
7962       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7963       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7964     }
7965   }
7966 }
7967
7968 /*-----------------------------------------------------------------*/
7969 /* shiftL2Left2Result - shift left two bytes from left to result   */
7970 /*-----------------------------------------------------------------*/
7971 static void shiftL2Left2Result (operand *left, int offl,
7972                                 operand *result, int offr, int shCount)
7973 {
7974   int same = pic16_sameRegs(AOP(result), AOP(left));
7975   int i;
7976
7977   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7978
7979   if (same && (offl != offr)) { // shift bytes
7980     if (offr > offl) {
7981        for(i=1;i>-1;i--) {
7982          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7983          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7984        }
7985     } else { // just treat as different later on
7986                 same = 0;
7987     }
7988   }
7989
7990   if(same) {
7991     switch(shCount) {
7992     case 0:
7993       break;
7994     case 1:
7995     case 2:
7996     case 3:
7997
7998       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7999       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8000       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8001
8002       while(--shCount) {
8003                 emitCLRC;
8004                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8005                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8006       }
8007
8008       break;
8009     case 4:
8010     case 5:
8011       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8012       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8013       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8014       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8015       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8016       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8017       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8018       if(shCount >=5) {
8019                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8020                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8021       }
8022       break;
8023     case 6:
8024       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8025       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8026       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8027       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8028       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8029       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8030       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8031       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8032       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8033       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8034       break;
8035     case 7:
8036       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8037       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8038       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8039       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8040       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8041     }
8042
8043   } else {
8044     switch(shCount) {
8045     case 0:
8046       break;
8047     case 1:
8048     case 2:
8049     case 3:
8050       /* note, use a mov/add for the shift since the mov has a
8051          chance of getting optimized out */
8052       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8053       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8054       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8055       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8056       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8057
8058       while(--shCount) {
8059                 emitCLRC;
8060                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8061                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8062       }
8063       break;
8064
8065     case 4:
8066     case 5:
8067       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8068       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8069       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8070       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8071       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8072       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8073       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8074       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8075
8076
8077       if(shCount == 5) {
8078                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8079                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8080       }
8081       break;
8082     case 6:
8083       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8084       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8085       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8086       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8087
8088       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8089       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8090       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8091       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8092       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8093       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8094       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8095       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8096       break;
8097     case 7:
8098       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8099       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8100       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8101       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8102       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8103     }
8104   }
8105
8106 }
8107 /*-----------------------------------------------------------------*/
8108 /* shiftR2Left2Result - shift right two bytes from left to result  */
8109 /*-----------------------------------------------------------------*/
8110 static void shiftR2Left2Result (operand *left, int offl,
8111                                 operand *result, int offr,
8112                                 int shCount, int sign)
8113 {
8114   int same = pic16_sameRegs(AOP(result), AOP(left));
8115   int i;
8116   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8117
8118   if (same && (offl != offr)) { // shift right bytes
8119     if (offr < offl) {
8120        for(i=0;i<2;i++) {
8121          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8122          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8123        }
8124     } else { // just treat as different later on
8125                 same = 0;
8126     }
8127   }
8128
8129   switch(shCount) {
8130   case 0:
8131     break;
8132   case 1:
8133   case 2:
8134   case 3:
8135     if(sign)
8136       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8137     else
8138       emitCLRC;
8139
8140     if(same) {
8141       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8142       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8143     } else {
8144       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8145       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8146       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8147       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8148     }
8149
8150     while(--shCount) {
8151       if(sign)
8152                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8153       else
8154                 emitCLRC;
8155       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8156       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8157     }
8158     break;
8159   case 4:
8160   case 5:
8161     if(same) {
8162
8163       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
8164       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
8165       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8166
8167       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8168       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
8169       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8170       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8171     } else {
8172       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8173       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8174       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8175
8176       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8177       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8178       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8179       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8180       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8181     }
8182
8183     if(shCount >=5) {
8184       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8185       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8186     }
8187
8188     if(sign) {
8189       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
8190       pic16_emitpcode(POC_BTFSC, 
8191                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
8192       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8193     }
8194
8195     break;
8196
8197   case 6:
8198     if(same) {
8199
8200       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8201       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8202
8203       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8204       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8205       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8206       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8207       if(sign) {
8208         pic16_emitpcode(POC_BTFSC, 
8209                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8210         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8211       }
8212       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8213       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
8214       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8215       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8216     } else {
8217       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8218       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8219       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8220       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8221       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8222       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8223       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8224       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8225       if(sign) {
8226         pic16_emitpcode(POC_BTFSC, 
8227                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8228         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8229       }
8230       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8231       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8232
8233         
8234     }
8235
8236     break;
8237   case 7:
8238     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8239     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8240     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8241     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8242     if(sign) {
8243       emitSKPNC;
8244       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8245     } else 
8246       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8247   }
8248 }
8249
8250
8251 /*-----------------------------------------------------------------*/
8252 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8253 /*-----------------------------------------------------------------*/
8254 static void shiftLLeftOrResult (operand *left, int offl,
8255                                 operand *result, int offr, int shCount)
8256 {
8257     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8258
8259     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8260     /* shift left accumulator */
8261     AccLsh(shCount);
8262     /* or with result */
8263     /* back to result */
8264     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8265 }
8266
8267 /*-----------------------------------------------------------------*/
8268 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8269 /*-----------------------------------------------------------------*/
8270 static void shiftRLeftOrResult (operand *left, int offl,
8271                                 operand *result, int offr, int shCount)
8272 {
8273     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8274     
8275     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8276     /* shift right accumulator */
8277     AccRsh(shCount, 1);
8278     /* or with result */
8279     /* back to result */
8280     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8281 }
8282
8283 /*-----------------------------------------------------------------*/
8284 /* genlshOne - left shift a one byte quantity by known count       */
8285 /*-----------------------------------------------------------------*/
8286 static void genlshOne (operand *result, operand *left, int shCount)
8287 {       
8288     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8289     shiftL1Left2Result(left, LSB, result, LSB, shCount);
8290 }
8291
8292 /*-----------------------------------------------------------------*/
8293 /* genlshTwo - left shift two bytes by known amount != 0           */
8294 /*-----------------------------------------------------------------*/
8295 static void genlshTwo (operand *result,operand *left, int shCount)
8296 {
8297     int size;
8298     
8299     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8300     size = pic16_getDataSize(result);
8301
8302     /* if shCount >= 8 */
8303     if (shCount >= 8) {
8304         shCount -= 8 ;
8305
8306         if (size > 1){
8307             if (shCount)
8308                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8309             else 
8310                 movLeft2Result(left, LSB, result, MSB16);
8311         }
8312         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8313     }
8314
8315     /*  1 <= shCount <= 7 */
8316     else {  
8317         if(size == 1)
8318             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
8319         else 
8320             shiftL2Left2Result(left, LSB, result, LSB, shCount);
8321     }
8322 }
8323
8324 /*-----------------------------------------------------------------*/
8325 /* shiftLLong - shift left one long from left to result            */
8326 /* offr = LSB or MSB16                                             */
8327 /*-----------------------------------------------------------------*/
8328 static void shiftLLong (operand *left, operand *result, int offr )
8329 {
8330     int size = AOP_SIZE(result);
8331     int same = pic16_sameRegs(AOP(left),AOP(result));
8332         int i;
8333
8334     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8335
8336         if (same && (offr == MSB16)) { //shift one byte
8337                 for(i=size-1;i>=MSB16;i--) {
8338                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8339                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8340                 }
8341         } else {
8342                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8343         }
8344         
8345     if (size >= LSB+offr ){
8346                 if (same) {
8347                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8348                 } else {
8349                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8350                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8351                 }
8352          }
8353
8354     if(size >= MSB16+offr){
8355                 if (same) {
8356                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8357                 } else {
8358                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8359                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8360                 }
8361     }
8362
8363     if(size >= MSB24+offr){
8364                 if (same) {
8365                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8366                 } else {
8367                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8368                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8369                 }
8370     }
8371
8372     if(size > MSB32+offr){
8373                 if (same) {
8374                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8375                 } else {
8376                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8377                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8378                 }
8379     }
8380     if(offr != LSB)
8381                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8382
8383 }
8384
8385 /*-----------------------------------------------------------------*/
8386 /* genlshFour - shift four byte by a known amount != 0             */
8387 /*-----------------------------------------------------------------*/
8388 static void genlshFour (operand *result, operand *left, int shCount)
8389 {
8390     int size;
8391
8392     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8393     size = AOP_SIZE(result);
8394
8395     /* if shifting more that 3 bytes */
8396     if (shCount >= 24 ) {
8397         shCount -= 24;
8398         if (shCount)
8399             /* lowest order of left goes to the highest
8400             order of the destination */
8401             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8402         else
8403             movLeft2Result(left, LSB, result, MSB32);
8404
8405                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8406                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8407                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8408
8409         return;
8410     }
8411
8412     /* more than two bytes */
8413     else if ( shCount >= 16 ) {
8414         /* lower order two bytes goes to higher order two bytes */
8415         shCount -= 16;
8416         /* if some more remaining */
8417         if (shCount)
8418             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8419         else {
8420             movLeft2Result(left, MSB16, result, MSB32);
8421             movLeft2Result(left, LSB, result, MSB24);
8422         }
8423                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8424                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8425         return;
8426     }    
8427
8428     /* if more than 1 byte */
8429     else if ( shCount >= 8 ) {
8430         /* lower order three bytes goes to higher order  three bytes */
8431         shCount -= 8;
8432         if(size == 2){
8433             if(shCount)
8434                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8435             else
8436                 movLeft2Result(left, LSB, result, MSB16);
8437         }
8438         else{   /* size = 4 */
8439             if(shCount == 0){
8440                 movLeft2Result(left, MSB24, result, MSB32);
8441                 movLeft2Result(left, MSB16, result, MSB24);
8442                 movLeft2Result(left, LSB, result, MSB16);
8443                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8444             }
8445             else if(shCount == 1)
8446                 shiftLLong(left, result, MSB16);
8447             else{
8448                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8449                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8450                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8451                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8452             }
8453         }
8454     }
8455
8456     /* 1 <= shCount <= 7 */
8457     else if(shCount <= 3)
8458     { 
8459         shiftLLong(left, result, LSB);
8460         while(--shCount >= 1)
8461             shiftLLong(result, result, LSB);
8462     }
8463     /* 3 <= shCount <= 7, optimize */
8464     else{
8465         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8466         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8467         shiftL2Left2Result(left, LSB, result, LSB, shCount);
8468     }
8469 }
8470
8471 /*-----------------------------------------------------------------*/
8472 /* genLeftShiftLiteral - left shifting by known count              */
8473 /*-----------------------------------------------------------------*/
8474 static void genLeftShiftLiteral (operand *left,
8475                                  operand *right,
8476                                  operand *result,
8477                                  iCode *ic)
8478 {    
8479     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8480     int size;
8481
8482     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8483     pic16_freeAsmop(right,NULL,ic,TRUE);
8484
8485     pic16_aopOp(left,ic,FALSE);
8486     pic16_aopOp(result,ic,FALSE);
8487
8488     size = getSize(operandType(result));
8489
8490 #if VIEW_SIZE
8491     pic16_emitcode("; shift left ","result %d, left %d",size,
8492              AOP_SIZE(left));
8493 #endif
8494
8495     /* I suppose that the left size >= result size */
8496     if(shCount == 0){
8497         while(size--){
8498             movLeft2Result(left, size, result, size);
8499         }
8500     }
8501
8502     else if(shCount >= (size * 8))
8503         while(size--)
8504             pic16_aopPut(AOP(result),zero,size);
8505     else{
8506         switch (size) {
8507             case 1:
8508                 genlshOne (result,left,shCount);
8509                 break;
8510
8511             case 2:
8512             case 3:
8513                 genlshTwo (result,left,shCount);
8514                 break;
8515
8516             case 4:
8517                 genlshFour (result,left,shCount);
8518                 break;
8519         }
8520     }
8521     pic16_freeAsmop(left,NULL,ic,TRUE);
8522     pic16_freeAsmop(result,NULL,ic,TRUE);
8523 }
8524
8525 /*-----------------------------------------------------------------*
8526  * genMultiAsm - repeat assembly instruction for size of register.
8527  * if endian == 1, then the high byte (i.e base address + size of 
8528  * register) is used first else the low byte is used first;
8529  *-----------------------------------------------------------------*/
8530 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8531 {
8532
8533   int offset = 0;
8534
8535   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8536
8537   if(!reg)
8538     return;
8539
8540   if(!endian) {
8541     endian = 1;
8542   } else {
8543     endian = -1;
8544     offset = size-1;
8545   }
8546
8547   while(size--) {
8548     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
8549     offset += endian;
8550   }
8551
8552 }
8553 /*-----------------------------------------------------------------*/
8554 /* genLeftShift - generates code for left shifting                 */
8555 /*-----------------------------------------------------------------*/
8556 static void genLeftShift (iCode *ic)
8557 {
8558   operand *left,*right, *result;
8559   int size, offset;
8560   char *l;
8561   symbol *tlbl , *tlbl1;
8562   pCodeOp *pctemp;
8563
8564   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8565
8566   right = IC_RIGHT(ic);
8567   left  = IC_LEFT(ic);
8568   result = IC_RESULT(ic);
8569
8570   pic16_aopOp(right,ic,FALSE);
8571
8572   /* if the shift count is known then do it 
8573      as efficiently as possible */
8574   if (AOP_TYPE(right) == AOP_LIT) {
8575     genLeftShiftLiteral (left,right,result,ic);
8576     return ;
8577   }
8578
8579   /* shift count is unknown then we have to form 
8580      a loop get the loop count in B : Note: we take
8581      only the lower order byte since shifting
8582      more that 32 bits make no sense anyway, ( the
8583      largest size of an object can be only 32 bits ) */  
8584
8585     
8586   pic16_aopOp(left,ic,FALSE);
8587   pic16_aopOp(result,ic,FALSE);
8588
8589   /* now move the left to the result if they are not the
8590      same */
8591   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8592       AOP_SIZE(result) > 1) {
8593
8594     size = AOP_SIZE(result);
8595     offset=0;
8596     while (size--) {
8597       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8598       if (*l == '@' && (IS_AOP_PREG(result))) {
8599
8600         pic16_emitcode("mov","a,%s",l);
8601         pic16_aopPut(AOP(result),"a",offset);
8602       } else {
8603         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8604         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8605         //pic16_aopPut(AOP(result),l,offset);
8606       }
8607       offset++;
8608     }
8609   }
8610
8611   size = AOP_SIZE(result);
8612
8613   /* if it is only one byte then */
8614   if (size == 1) {
8615     if(optimized_for_speed) {
8616       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8617       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
8618       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
8619       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8620       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8621       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8622       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8623       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
8624       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
8625       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
8626       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8627       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8628     } else {
8629
8630       tlbl = newiTempLabel(NULL);
8631       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8632                 pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8633                 pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8634       }
8635
8636       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8637       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8638       pic16_emitpLabel(tlbl->key);
8639       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8640       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8641       emitSKPC;
8642       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8643     }
8644     goto release ;
8645   }
8646     
8647   if (pic16_sameRegs(AOP(left),AOP(result))) {
8648
8649     tlbl = newiTempLabel(NULL);
8650     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8651     genMultiAsm(POC_RRCF, result, size,1);
8652     pic16_emitpLabel(tlbl->key);
8653     genMultiAsm(POC_RLCF, result, size,0);
8654     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8655     emitSKPC;
8656     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8657     goto release;
8658   }
8659
8660   //tlbl = newiTempLabel(NULL);
8661   //offset = 0 ;   
8662   //tlbl1 = newiTempLabel(NULL);
8663
8664   //reAdjustPreg(AOP(result));    
8665     
8666   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
8667   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8668   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8669   //MOVA(l);
8670   //pic16_emitcode("add","a,acc");         
8671   //pic16_aopPut(AOP(result),"a",offset++);
8672   //while (--size) {
8673   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8674   //  MOVA(l);
8675   //  pic16_emitcode("rlc","a");         
8676   //  pic16_aopPut(AOP(result),"a",offset++);
8677   //}
8678   //reAdjustPreg(AOP(result));
8679
8680   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8681   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8682
8683
8684   tlbl = newiTempLabel(NULL);
8685   tlbl1= newiTempLabel(NULL);
8686
8687   size = AOP_SIZE(result);
8688   offset = 1;
8689
8690   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8691
8692   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8693
8694   /* offset should be 0, 1 or 3 */
8695   
8696   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8697   emitSKPNZ;
8698   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8699
8700   pic16_emitpcode(POC_MOVWF, pctemp);
8701
8702
8703   pic16_emitpLabel(tlbl->key);
8704
8705   emitCLRC;
8706   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
8707   while(--size)
8708     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
8709
8710   pic16_emitpcode(POC_DECFSZ,  pctemp);
8711   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8712   pic16_emitpLabel(tlbl1->key);
8713
8714   pic16_popReleaseTempReg(pctemp);
8715
8716
8717  release:
8718   pic16_freeAsmop (right,NULL,ic,TRUE);
8719   pic16_freeAsmop(left,NULL,ic,TRUE);
8720   pic16_freeAsmop(result,NULL,ic,TRUE);
8721 }
8722
8723 /*-----------------------------------------------------------------*/
8724 /* genrshOne - right shift a one byte quantity by known count      */
8725 /*-----------------------------------------------------------------*/
8726 static void genrshOne (operand *result, operand *left,
8727                        int shCount, int sign)
8728 {
8729     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8730     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8731 }
8732
8733 /*-----------------------------------------------------------------*/
8734 /* genrshTwo - right shift two bytes by known amount != 0          */
8735 /*-----------------------------------------------------------------*/
8736 static void genrshTwo (operand *result,operand *left,
8737                        int shCount, int sign)
8738 {
8739   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8740   /* if shCount >= 8 */
8741   if (shCount >= 8) {
8742     shCount -= 8 ;
8743     if (shCount)
8744       shiftR1Left2Result(left, MSB16, result, LSB,
8745                          shCount, sign);
8746     else
8747       movLeft2Result(left, MSB16, result, LSB);
8748
8749     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8750
8751     if(sign) {
8752       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8753       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8754     }
8755   }
8756
8757   /*  1 <= shCount <= 7 */
8758   else
8759     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
8760 }
8761
8762 /*-----------------------------------------------------------------*/
8763 /* shiftRLong - shift right one long from left to result           */
8764 /* offl = LSB or MSB16                                             */
8765 /*-----------------------------------------------------------------*/
8766 static void shiftRLong (operand *left, int offl,
8767                         operand *result, int sign)
8768 {
8769     int size = AOP_SIZE(result);
8770     int same = pic16_sameRegs(AOP(left),AOP(result));
8771     int i;
8772     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8773
8774         if (same && (offl == MSB16)) { //shift one byte right
8775                 for(i=MSB16;i<size;i++) {
8776                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8777                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8778                 }
8779         }
8780
8781     if(sign)
8782                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8783         else
8784                 emitCLRC;
8785
8786         if (same) {
8787                 if (offl == LSB)
8788                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8789         } else {
8790         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8791         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8792         }
8793
8794     if(offl == MSB16) {
8795         /* add sign of "a" */
8796         pic16_addSign(result, MSB32, sign);
8797         }
8798
8799         if (same) {
8800         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8801         } else {
8802         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8803         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8804         }
8805         
8806         if (same) {
8807         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8808         } else {
8809         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8810         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8811         }
8812
8813         if (same) {
8814         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8815         } else {
8816         if(offl == LSB){
8817                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8818                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8819         }
8820         }
8821 }
8822
8823 /*-----------------------------------------------------------------*/
8824 /* genrshFour - shift four byte by a known amount != 0             */
8825 /*-----------------------------------------------------------------*/
8826 static void genrshFour (operand *result, operand *left,
8827                         int shCount, int sign)
8828 {
8829   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8830   /* if shifting more that 3 bytes */
8831   if(shCount >= 24 ) {
8832     shCount -= 24;
8833     if(shCount)
8834       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8835     else
8836       movLeft2Result(left, MSB32, result, LSB);
8837
8838     pic16_addSign(result, MSB16, sign);
8839   }
8840   else if(shCount >= 16){
8841     shCount -= 16;
8842     if(shCount)
8843       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8844     else{
8845       movLeft2Result(left, MSB24, result, LSB);
8846       movLeft2Result(left, MSB32, result, MSB16);
8847     }
8848     pic16_addSign(result, MSB24, sign);
8849   }
8850   else if(shCount >= 8){
8851     shCount -= 8;
8852     if(shCount == 1)
8853       shiftRLong(left, MSB16, result, sign);
8854     else if(shCount == 0){
8855       movLeft2Result(left, MSB16, result, LSB);
8856       movLeft2Result(left, MSB24, result, MSB16);
8857       movLeft2Result(left, MSB32, result, MSB24);
8858       pic16_addSign(result, MSB32, sign);
8859     }
8860     else{ //shcount >= 2
8861       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8862       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8863       /* the last shift is signed */
8864       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8865       pic16_addSign(result, MSB32, sign);
8866     }
8867   }
8868   else{   /* 1 <= shCount <= 7 */
8869     if(shCount <= 2){
8870       shiftRLong(left, LSB, result, sign);
8871       if(shCount == 2)
8872         shiftRLong(result, LSB, result, sign);
8873     }
8874     else{
8875       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8876       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8877       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8878     }
8879   }
8880 }
8881
8882 /*-----------------------------------------------------------------*/
8883 /* genRightShiftLiteral - right shifting by known count            */
8884 /*-----------------------------------------------------------------*/
8885 static void genRightShiftLiteral (operand *left,
8886                                   operand *right,
8887                                   operand *result,
8888                                   iCode *ic,
8889                                   int sign)
8890 {    
8891   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8892   int lsize,res_size;
8893
8894   pic16_freeAsmop(right,NULL,ic,TRUE);
8895
8896   pic16_aopOp(left,ic,FALSE);
8897   pic16_aopOp(result,ic,FALSE);
8898
8899   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8900
8901 #if VIEW_SIZE
8902   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8903                  AOP_SIZE(left));
8904 #endif
8905
8906   lsize = pic16_getDataSize(left);
8907   res_size = pic16_getDataSize(result);
8908   /* test the LEFT size !!! */
8909
8910   /* I suppose that the left size >= result size */
8911   if(shCount == 0){
8912     while(res_size--)
8913       movLeft2Result(left, lsize, result, res_size);
8914   }
8915
8916   else if(shCount >= (lsize * 8)){
8917
8918     if(res_size == 1) {
8919       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8920       if(sign) {
8921         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8922         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8923       }
8924     } else {
8925
8926       if(sign) {
8927         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8928         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8929         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8930         while(res_size--)
8931           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8932
8933       } else {
8934
8935         while(res_size--)
8936           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8937       }
8938     }
8939   } else {
8940
8941     switch (res_size) {
8942     case 1:
8943       genrshOne (result,left,shCount,sign);
8944       break;
8945
8946     case 2:
8947       genrshTwo (result,left,shCount,sign);
8948       break;
8949
8950     case 4:
8951       genrshFour (result,left,shCount,sign);
8952       break;
8953     default :
8954       break;
8955     }
8956
8957   }
8958
8959   pic16_freeAsmop(left,NULL,ic,TRUE);
8960   pic16_freeAsmop(result,NULL,ic,TRUE);
8961 }
8962
8963 /*-----------------------------------------------------------------*/
8964 /* genSignedRightShift - right shift of signed number              */
8965 /*-----------------------------------------------------------------*/
8966 static void genSignedRightShift (iCode *ic)
8967 {
8968   operand *right, *left, *result;
8969   int size, offset;
8970   //  char *l;
8971   symbol *tlbl, *tlbl1 ;
8972   pCodeOp *pctemp;
8973
8974   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8975
8976   /* we do it the hard way put the shift count in b
8977      and loop thru preserving the sign */
8978   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8979
8980   right = IC_RIGHT(ic);
8981   left  = IC_LEFT(ic);
8982   result = IC_RESULT(ic);
8983
8984   pic16_aopOp(right,ic,FALSE);  
8985   pic16_aopOp(left,ic,FALSE);
8986   pic16_aopOp(result,ic,FALSE);
8987
8988
8989   if ( AOP_TYPE(right) == AOP_LIT) {
8990     genRightShiftLiteral (left,right,result,ic,1);
8991     return ;
8992   }
8993   /* shift count is unknown then we have to form 
8994      a loop get the loop count in B : Note: we take
8995      only the lower order byte since shifting
8996      more that 32 bits make no sense anyway, ( the
8997      largest size of an object can be only 32 bits ) */  
8998
8999   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9000   //pic16_emitcode("inc","b");
9001   //pic16_freeAsmop (right,NULL,ic,TRUE);
9002   //pic16_aopOp(left,ic,FALSE);
9003   //pic16_aopOp(result,ic,FALSE);
9004
9005   /* now move the left to the result if they are not the
9006      same */
9007   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9008       AOP_SIZE(result) > 1) {
9009
9010     size = AOP_SIZE(result);
9011     offset=0;
9012     while (size--) { 
9013       /*
9014         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9015         if (*l == '@' && IS_AOP_PREG(result)) {
9016
9017         pic16_emitcode("mov","a,%s",l);
9018         pic16_aopPut(AOP(result),"a",offset);
9019         } else
9020         pic16_aopPut(AOP(result),l,offset);
9021       */
9022       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
9023       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
9024
9025       offset++;
9026     }
9027   }
9028
9029   /* mov the highest order bit to OVR */    
9030   tlbl = newiTempLabel(NULL);
9031   tlbl1= newiTempLabel(NULL);
9032
9033   size = AOP_SIZE(result);
9034   offset = size - 1;
9035
9036   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
9037
9038   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9039
9040   /* offset should be 0, 1 or 3 */
9041   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
9042   emitSKPNZ;
9043   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9044
9045   pic16_emitpcode(POC_MOVWF, pctemp);
9046
9047
9048   pic16_emitpLabel(tlbl->key);
9049
9050   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
9051   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
9052
9053   while(--size) {
9054     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
9055   }
9056
9057   pic16_emitpcode(POC_DECFSZ,  pctemp);
9058   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9059   pic16_emitpLabel(tlbl1->key);
9060
9061   pic16_popReleaseTempReg(pctemp);
9062 #if 0
9063   size = AOP_SIZE(result);
9064   offset = size - 1;
9065   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
9066   pic16_emitcode("rlc","a");
9067   pic16_emitcode("mov","ov,c");
9068   /* if it is only one byte then */
9069   if (size == 1) {
9070     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9071     MOVA(l);
9072     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9073     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9074     pic16_emitcode("mov","c,ov");
9075     pic16_emitcode("rrc","a");
9076     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9077     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9078     pic16_aopPut(AOP(result),"a",0);
9079     goto release ;
9080   }
9081
9082   reAdjustPreg(AOP(result));
9083   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9084   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9085   pic16_emitcode("mov","c,ov");
9086   while (size--) {
9087     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9088     MOVA(l);
9089     pic16_emitcode("rrc","a");         
9090     pic16_aopPut(AOP(result),"a",offset--);
9091   }
9092   reAdjustPreg(AOP(result));
9093   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9094   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9095
9096  release:
9097 #endif
9098
9099   pic16_freeAsmop(left,NULL,ic,TRUE);
9100   pic16_freeAsmop(result,NULL,ic,TRUE);
9101   pic16_freeAsmop(right,NULL,ic,TRUE);
9102 }
9103
9104 /*-----------------------------------------------------------------*/
9105 /* genRightShift - generate code for right shifting                */
9106 /*-----------------------------------------------------------------*/
9107 static void genRightShift (iCode *ic)
9108 {
9109     operand *right, *left, *result;
9110     sym_link *letype ;
9111     int size, offset;
9112     char *l;
9113     symbol *tlbl, *tlbl1 ;
9114
9115     /* if signed then we do it the hard way preserve the
9116     sign bit moving it inwards */
9117     letype = getSpec(operandType(IC_LEFT(ic)));
9118     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9119
9120     if (!SPEC_USIGN(letype)) {
9121         genSignedRightShift (ic);
9122         return ;
9123     }
9124
9125     /* signed & unsigned types are treated the same : i.e. the
9126     signed is NOT propagated inwards : quoting from the
9127     ANSI - standard : "for E1 >> E2, is equivalent to division
9128     by 2**E2 if unsigned or if it has a non-negative value,
9129     otherwise the result is implementation defined ", MY definition
9130     is that the sign does not get propagated */
9131
9132     right = IC_RIGHT(ic);
9133     left  = IC_LEFT(ic);
9134     result = IC_RESULT(ic);
9135
9136     pic16_aopOp(right,ic,FALSE);
9137
9138     /* if the shift count is known then do it 
9139     as efficiently as possible */
9140     if (AOP_TYPE(right) == AOP_LIT) {
9141         genRightShiftLiteral (left,right,result,ic, 0);
9142         return ;
9143     }
9144
9145     /* shift count is unknown then we have to form 
9146     a loop get the loop count in B : Note: we take
9147     only the lower order byte since shifting
9148     more that 32 bits make no sense anyway, ( the
9149     largest size of an object can be only 32 bits ) */  
9150
9151     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9152     pic16_emitcode("inc","b");
9153     pic16_aopOp(left,ic,FALSE);
9154     pic16_aopOp(result,ic,FALSE);
9155
9156     /* now move the left to the result if they are not the
9157     same */
9158     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9159         AOP_SIZE(result) > 1) {
9160
9161         size = AOP_SIZE(result);
9162         offset=0;
9163         while (size--) {
9164             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9165             if (*l == '@' && IS_AOP_PREG(result)) {
9166
9167                 pic16_emitcode("mov","a,%s",l);
9168                 pic16_aopPut(AOP(result),"a",offset);
9169             } else
9170                 pic16_aopPut(AOP(result),l,offset);
9171             offset++;
9172         }
9173     }
9174
9175     tlbl = newiTempLabel(NULL);
9176     tlbl1= newiTempLabel(NULL);
9177     size = AOP_SIZE(result);
9178     offset = size - 1;
9179
9180     /* if it is only one byte then */
9181     if (size == 1) {
9182
9183       tlbl = newiTempLabel(NULL);
9184       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9185         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9186         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9187       }
9188
9189       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9190       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9191       pic16_emitpLabel(tlbl->key);
9192       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9193       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9194       emitSKPC;
9195       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9196
9197       goto release ;
9198     }
9199
9200     reAdjustPreg(AOP(result));
9201     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9202     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9203     CLRC;
9204     while (size--) {
9205         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9206         MOVA(l);
9207         pic16_emitcode("rrc","a");         
9208         pic16_aopPut(AOP(result),"a",offset--);
9209     }
9210     reAdjustPreg(AOP(result));
9211
9212     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9213     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9214
9215 release:
9216     pic16_freeAsmop(left,NULL,ic,TRUE);
9217     pic16_freeAsmop (right,NULL,ic,TRUE);
9218     pic16_freeAsmop(result,NULL,ic,TRUE);
9219 }
9220
9221
9222 void pic16_loadFSR0(operand *op)
9223 {
9224         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9225 }
9226
9227 /*-----------------------------------------------------------------*/
9228 /* genUnpackBits - generates code for unpacking bits               */
9229 /*-----------------------------------------------------------------*/
9230 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
9231 {    
9232     int shCnt ;
9233     int rlen = 0 ;
9234     sym_link *etype;
9235     int offset = 0 ;
9236
9237         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9238         etype = getSpec(operandType(result));
9239
9240         /* the following call to pic16_loadFSR0 is temporary until
9241          * optimization to handle single bit assignments is added
9242          * to the function. Until then use the old safe way! -- VR */
9243         pic16_loadFSR0( left );
9244  
9245         /* read the first byte  */
9246         switch (ptype) {
9247                 case POINTER:
9248                 case IPOINTER:
9249                 case PPOINTER:
9250                 case FPOINTER:
9251                 case GPOINTER:
9252                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9253                         break;
9254                 case CPOINTER:
9255                         pic16_emitcode("clr","a");
9256                         pic16_emitcode("movc","a","@a+dptr");
9257                         break;
9258         }
9259         
9260
9261         /* if we have bitdisplacement then it fits   */
9262         /* into this byte completely or if length is */
9263         /* less than a byte                          */
9264         if ((shCnt = SPEC_BSTR(etype)) || 
9265                 (SPEC_BLEN(etype) <= 8))  {
9266
9267                 /* shift right acc */
9268                 AccRsh(shCnt, 0);
9269
9270                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9271                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9272
9273 /* VR -- normally I would use the following, but since we use the hack,
9274  * to avoid the masking from AccRsh, why not mask it right now? */
9275
9276 /*
9277                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9278 */
9279
9280                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9281           return ;
9282         }
9283
9284
9285
9286         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9287         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9288         exit(-1);
9289
9290     /* bit field did not fit in a byte  */
9291     rlen = SPEC_BLEN(etype) - 8;
9292     pic16_aopPut(AOP(result),"a",offset++);
9293
9294     while (1)  {
9295
9296         switch (ptype) {
9297         case POINTER:
9298         case IPOINTER:
9299             pic16_emitcode("inc","%s",rname);
9300             pic16_emitcode("mov","a,@%s",rname);
9301             break;
9302             
9303         case PPOINTER:
9304             pic16_emitcode("inc","%s",rname);
9305             pic16_emitcode("movx","a,@%s",rname);
9306             break;
9307
9308         case FPOINTER:
9309             pic16_emitcode("inc","dptr");
9310             pic16_emitcode("movx","a,@dptr");
9311             break;
9312             
9313         case CPOINTER:
9314             pic16_emitcode("clr","a");
9315             pic16_emitcode("inc","dptr");
9316             pic16_emitcode("movc","a","@a+dptr");
9317             break;
9318             
9319         case GPOINTER:
9320             pic16_emitcode("inc","dptr");
9321             pic16_emitcode("lcall","__gptrget");
9322             break;
9323         }
9324
9325         rlen -= 8;            
9326         /* if we are done */
9327         if ( rlen <= 0 )
9328             break ;
9329         
9330         pic16_aopPut(AOP(result),"a",offset++);
9331                               
9332     }
9333     
9334     if (rlen) {
9335         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9336         pic16_aopPut(AOP(result),"a",offset);          
9337     }
9338     
9339     return ;
9340 }
9341
9342
9343 static void genDataPointerGet(operand *left,
9344                               operand *result,
9345                               iCode *ic)
9346 {
9347   int size, offset = 0, leoffset=0 ;
9348
9349         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9350         pic16_aopOp(result, ic, FALSE);
9351
9352         size = AOP_SIZE(result);
9353 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9354
9355
9356 #if 0
9357         /* The following tests may save a redudant movff instruction when
9358          * accessing unions */
9359          
9360         /* if they are the same */
9361         if (operandsEqu (left, result)) {
9362                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9363                 goto release;
9364         }
9365 #endif
9366
9367 #if 0
9368         /* if they are the same registers */
9369         if (pic16_sameRegs(AOP(left),AOP(result))) {
9370                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9371                 goto release;
9372         }
9373 #endif
9374
9375 #if 1
9376         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9377                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9378                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9379                 goto release;
9380         }
9381 #endif
9382
9383
9384 #if 0
9385         if ( AOP_TYPE(left) == AOP_PCODE) {
9386                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
9387                                 AOP(left)->aopu.pcop->name,
9388                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
9389                                 PCOR(AOP(left)->aopu.pcop)->instance:
9390                                 PCOI(AOP(left)->aopu.pcop)->offset);
9391         }
9392 #endif
9393
9394         if(AOP(left)->aopu.pcop->type == PO_DIR)
9395                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9396
9397         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9398
9399         while (size--) {
9400                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9401                 
9402                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9403                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9404                         mov2w(AOP(left), offset); // patch 8
9405                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9406                 } else {
9407                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9408                                 pic16_popGet(AOP(left), offset), //patch 8
9409                                 pic16_popGet(AOP(result), offset)));
9410                 }
9411
9412                 offset++;
9413                 leoffset++;
9414         }
9415
9416 release:
9417     pic16_freeAsmop(result,NULL,ic,TRUE);
9418 }
9419
9420
9421
9422 /*-----------------------------------------------------------------*/
9423 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
9424 /*-----------------------------------------------------------------*/
9425 static void genNearPointerGet (operand *left, 
9426                                operand *result, 
9427                                iCode *ic)
9428 {
9429     asmop *aop = NULL;
9430     //regs *preg = NULL ;
9431     sym_link *rtype, *retype;
9432     sym_link *ltype = operandType(left);    
9433
9434         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9435         rtype = operandType(result);
9436         retype= getSpec(rtype);
9437     
9438         pic16_aopOp(left,ic,FALSE);
9439
9440 //      pic16_DumpOp("(left)",left);
9441 //      pic16_DumpOp("(result)",result);
9442
9443         /* if left is rematerialisable and
9444          * result is not bit variable type and
9445          * the left is pointer to data space i.e
9446          * lower 128 bytes of space */
9447         if (AOP_TYPE(left) == AOP_PCODE
9448                 && !IS_BITFIELD(retype)
9449                 && DCL_TYPE(ltype) == POINTER) {
9450
9451                 genDataPointerGet (left,result,ic);
9452                 pic16_freeAsmop(left, NULL, ic, TRUE);
9453           return ;
9454         }
9455     
9456         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9457
9458         /* if the value is already in a pointer register
9459          * then don't need anything more */
9460         if (!AOP_INPREG(AOP(left))) {
9461                 /* otherwise get a free pointer register */
9462                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9463                 
9464                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9465                 if( (AOP_TYPE(left) == AOP_PCODE) 
9466                         && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9467                                 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9468                 {
9469                         if(!IS_BITFIELD(retype))
9470                                 pic16_loadFSR0( left );  // patch 10
9471                 } else {
9472                         // set up FSR0 with address from left
9473                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9474                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9475                 }
9476         }
9477 //       else
9478 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9479     
9480         pic16_aopOp (result,ic,FALSE);
9481     
9482       /* if bitfield then unpack the bits */
9483     if (IS_BITFIELD(retype)) 
9484         genUnpackBits (result, left, NULL, POINTER);
9485     else {
9486         /* we have can just get the values */
9487       int size = AOP_SIZE(result);
9488       int offset = 0;   
9489         
9490       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9491
9492
9493         /* fsr0 is loaded already -- VR */
9494 //      pic16_loadFSR0( left );
9495
9496 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9497 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9498       while(size--) {
9499
9500         if(size) {
9501                 pic16_emitpcode(POC_MOVFF,
9502                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9503                                 pic16_popGet(AOP(result), offset++)));
9504         } else {
9505                 pic16_emitpcode(POC_MOVFF,
9506                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9507                                 pic16_popGet(AOP(result), offset++)));
9508         }
9509       }
9510 #if 0
9511 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9512 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9513         if(size)
9514           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9515 #endif
9516 /*
9517         while (size--) {
9518             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9519
9520                 pic16_emitcode("mov","a,@%s",rname);
9521                 pic16_aopPut(AOP(result),"a",offset);
9522             } else {
9523                 sprintf(buffer,"@%s",rname);
9524                 pic16_aopPut(AOP(result),buffer,offset);
9525             }
9526             offset++ ;
9527             if (size)
9528                 pic16_emitcode("inc","%s",rname);
9529         }
9530 */
9531     }
9532
9533     /* now some housekeeping stuff */
9534     if (aop) {
9535         /* we had to allocate for this iCode */
9536     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9537         pic16_freeAsmop(NULL,aop,ic,TRUE);
9538     } else { 
9539         /* we did not allocate which means left
9540            already in a pointer register, then
9541            if size > 0 && this could be used again
9542            we have to point it back to where it 
9543            belongs */
9544     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9545         if (AOP_SIZE(result) > 1 &&
9546             !OP_SYMBOL(left)->remat &&
9547             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9548               ic->depth )) {
9549 //          int size = AOP_SIZE(result) - 1;
9550 //          while (size--)
9551 //              pic16_emitcode("dec","%s",rname);
9552         }
9553     }
9554
9555     /* done */
9556     pic16_freeAsmop(left,NULL,ic,TRUE);
9557     pic16_freeAsmop(result,NULL,ic,TRUE);
9558      
9559 }
9560
9561 /*-----------------------------------------------------------------*/
9562 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
9563 /*-----------------------------------------------------------------*/
9564 static void genPagedPointerGet (operand *left, 
9565                                operand *result, 
9566                                iCode *ic)
9567 {
9568     asmop *aop = NULL;
9569     regs *preg = NULL ;
9570     char *rname ;
9571     sym_link *rtype, *retype;    
9572
9573     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9574
9575     rtype = operandType(result);
9576     retype= getSpec(rtype);
9577     
9578     pic16_aopOp(left,ic,FALSE);
9579
9580   /* if the value is already in a pointer register
9581        then don't need anything more */
9582     if (!AOP_INPREG(AOP(left))) {
9583         /* otherwise get a free pointer register */
9584         aop = newAsmop(0);
9585         preg = getFreePtr(ic,&aop,FALSE);
9586         pic16_emitcode("mov","%s,%s",
9587                 preg->name,
9588                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9589         rname = preg->name ;
9590     } else
9591         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9592     
9593     pic16_freeAsmop(left,NULL,ic,TRUE);
9594     pic16_aopOp (result,ic,FALSE);
9595
9596     /* if bitfield then unpack the bits */
9597     if (IS_BITFIELD(retype)) 
9598         genUnpackBits (result,left,rname,PPOINTER);
9599     else {
9600         /* we have can just get the values */
9601         int size = AOP_SIZE(result);
9602         int offset = 0 ;        
9603         
9604         while (size--) {
9605             
9606             pic16_emitcode("movx","a,@%s",rname);
9607             pic16_aopPut(AOP(result),"a",offset);
9608             
9609             offset++ ;
9610             
9611             if (size)
9612                 pic16_emitcode("inc","%s",rname);
9613         }
9614     }
9615
9616     /* now some housekeeping stuff */
9617     if (aop) {
9618         /* we had to allocate for this iCode */
9619         pic16_freeAsmop(NULL,aop,ic,TRUE);
9620     } else { 
9621         /* we did not allocate which means left
9622            already in a pointer register, then
9623            if size > 0 && this could be used again
9624            we have to point it back to where it 
9625            belongs */
9626         if (AOP_SIZE(result) > 1 &&
9627             !OP_SYMBOL(left)->remat &&
9628             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9629               ic->depth )) {
9630             int size = AOP_SIZE(result) - 1;
9631             while (size--)
9632                 pic16_emitcode("dec","%s",rname);
9633         }
9634     }
9635
9636     /* done */
9637     pic16_freeAsmop(result,NULL,ic,TRUE);
9638     
9639         
9640 }
9641
9642 /*-----------------------------------------------------------------*/
9643 /* genFarPointerGet - gget value from far space                    */
9644 /*-----------------------------------------------------------------*/
9645 static void genFarPointerGet (operand *left,
9646                               operand *result, iCode *ic)
9647 {
9648     int size, offset ;
9649     sym_link *retype = getSpec(operandType(result));
9650
9651     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9652
9653     pic16_aopOp(left,ic,FALSE);
9654
9655     /* if the operand is already in dptr 
9656     then we do nothing else we move the value to dptr */
9657     if (AOP_TYPE(left) != AOP_STR) {
9658         /* if this is remateriazable */
9659         if (AOP_TYPE(left) == AOP_IMMD)
9660             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9661         else { /* we need to get it byte by byte */
9662             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9663             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9664             if (options.model == MODEL_FLAT24)
9665             {
9666                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9667             }
9668         }
9669     }
9670     /* so dptr know contains the address */
9671     pic16_freeAsmop(left,NULL,ic,TRUE);
9672     pic16_aopOp(result,ic,FALSE);
9673
9674     /* if bit then unpack */
9675     if (IS_BITFIELD(retype)) 
9676         genUnpackBits(result,left,"dptr",FPOINTER);
9677     else {
9678         size = AOP_SIZE(result);
9679         offset = 0 ;
9680
9681         while (size--) {
9682             pic16_emitcode("movx","a,@dptr");
9683             pic16_aopPut(AOP(result),"a",offset++);
9684             if (size)
9685                 pic16_emitcode("inc","dptr");
9686         }
9687     }
9688
9689     pic16_freeAsmop(result,NULL,ic,TRUE);
9690 }
9691 #if 0
9692 /*-----------------------------------------------------------------*/
9693 /* genCodePointerGet - get value from code space                  */
9694 /*-----------------------------------------------------------------*/
9695 static void genCodePointerGet (operand *left,
9696                                 operand *result, iCode *ic)
9697 {
9698     int size, offset ;
9699     sym_link *retype = getSpec(operandType(result));
9700
9701     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9702
9703     pic16_aopOp(left,ic,FALSE);
9704
9705     /* if the operand is already in dptr 
9706     then we do nothing else we move the value to dptr */
9707     if (AOP_TYPE(left) != AOP_STR) {
9708         /* if this is remateriazable */
9709         if (AOP_TYPE(left) == AOP_IMMD)
9710             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9711         else { /* we need to get it byte by byte */
9712             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9713             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9714             if (options.model == MODEL_FLAT24)
9715             {
9716                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9717             }
9718         }
9719     }
9720     /* so dptr know contains the address */
9721     pic16_freeAsmop(left,NULL,ic,TRUE);
9722     pic16_aopOp(result,ic,FALSE);
9723
9724     /* if bit then unpack */
9725     if (IS_BITFIELD(retype)) 
9726         genUnpackBits(result,left,"dptr",CPOINTER);
9727     else {
9728         size = AOP_SIZE(result);
9729         offset = 0 ;
9730
9731         while (size--) {
9732             pic16_emitcode("clr","a");
9733             pic16_emitcode("movc","a,@a+dptr");
9734             pic16_aopPut(AOP(result),"a",offset++);
9735             if (size)
9736                 pic16_emitcode("inc","dptr");
9737         }
9738     }
9739
9740     pic16_freeAsmop(result,NULL,ic,TRUE);
9741 }
9742 #endif
9743 /*-----------------------------------------------------------------*/
9744 /* genGenPointerGet - gget value from generic pointer space        */
9745 /*-----------------------------------------------------------------*/
9746 static void genGenPointerGet (operand *left,
9747                               operand *result, iCode *ic)
9748 {
9749   int size, offset, lit;
9750   sym_link *retype = getSpec(operandType(result));
9751
9752         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9753         pic16_aopOp(left,ic,FALSE);
9754         pic16_aopOp(result,ic,FALSE);
9755         size = AOP_SIZE(result);
9756
9757         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9758
9759         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9760
9761                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9762                 // load FSR0 from immediate
9763                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9764
9765 //              pic16_loadFSR0( left );
9766
9767                 offset = 0;
9768                 while(size--) {
9769                         if(size) {
9770                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9771                         } else {
9772                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9773                         }
9774                         offset++;
9775                 }
9776                 goto release;
9777
9778         }
9779         else { /* we need to get it byte by byte */
9780                 // set up FSR0 with address from left
9781                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9782                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9783
9784                 offset = 0 ;
9785
9786                 while(size--) {
9787                         if(size) {
9788                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9789                         } else {
9790                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9791                         }
9792                         offset++;
9793                 }
9794                 goto release;
9795         }
9796
9797   /* if bit then unpack */
9798         if (IS_BITFIELD(retype)) 
9799                 genUnpackBits(result,left,"BAD",GPOINTER);
9800
9801         release:
9802         pic16_freeAsmop(left,NULL,ic,TRUE);
9803         pic16_freeAsmop(result,NULL,ic,TRUE);
9804
9805 }
9806
9807 /*-----------------------------------------------------------------*/
9808 /* genConstPointerGet - get value from const generic pointer space */
9809 /*-----------------------------------------------------------------*/
9810 static void genConstPointerGet (operand *left,
9811                                 operand *result, iCode *ic)
9812 {
9813   //sym_link *retype = getSpec(operandType(result));
9814   // symbol *albl = newiTempLabel(NULL);        // patch 15
9815   // symbol *blbl = newiTempLabel(NULL);        //
9816   // PIC_OPCODE poc;                            // patch 15
9817   int size;
9818   int offset = 0;
9819
9820   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9821   pic16_aopOp(left,ic,FALSE);
9822   pic16_aopOp(result,ic,TRUE);
9823   size = AOP_SIZE(result);
9824
9825   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9826
9827   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9828 #if 0                                                                   // patch 15
9829   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9830   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9831   pic16_emitpLabel(albl->key);
9832
9833   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9834     
9835   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9836   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9837   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9838   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9839   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9840
9841   pic16_emitpLabel(blbl->key);
9842
9843   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9844 #endif                                                                  // patch 15
9845
9846
9847   // set up table pointer
9848   if( (AOP_TYPE(left) == AOP_PCODE) 
9849       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9850           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
9851     {
9852       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9853       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9854       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9855       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9856       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9857       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9858     }
9859   else
9860     {
9861       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9862       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9863       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9864     }
9865
9866
9867   while(size--)
9868     {
9869       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9870       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9871       offset++;
9872     }
9873     
9874   pic16_freeAsmop(left,NULL,ic,TRUE);
9875   pic16_freeAsmop(result,NULL,ic,TRUE);
9876
9877 }
9878
9879
9880 /*-----------------------------------------------------------------*/
9881 /* genPointerGet - generate code for pointer get                   */
9882 /*-----------------------------------------------------------------*/
9883 static void genPointerGet (iCode *ic)
9884 {
9885     operand *left, *result ;
9886     sym_link *type, *etype;
9887     int p_type;
9888
9889     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9890
9891     left = IC_LEFT(ic);
9892     result = IC_RESULT(ic) ;
9893
9894     /* depending on the type of pointer we need to
9895     move it to the correct pointer register */
9896     type = operandType(left);
9897     etype = getSpec(type);
9898
9899 #if 0
9900     if (IS_PTR_CONST(type))
9901 #else
9902     if (IS_CODEPTR(type))
9903 #endif
9904       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9905
9906     /* if left is of type of pointer then it is simple */
9907     if (IS_PTR(type) && !IS_FUNC(type->next)) 
9908         p_type = DCL_TYPE(type);
9909     else {
9910         /* we have to go by the storage class */
9911         p_type = PTR_TYPE(SPEC_OCLS(etype));
9912
9913         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9914
9915         if (SPEC_OCLS(etype)->codesp ) {
9916           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9917           //p_type = CPOINTER ; 
9918         }
9919         else
9920             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9921               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9922                /*p_type = FPOINTER ;*/ 
9923             else
9924                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9925                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9926 /*                  p_type = PPOINTER; */
9927                 else
9928                     if (SPEC_OCLS(etype) == idata )
9929                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9930 /*                      p_type = IPOINTER; */
9931                     else
9932                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9933 /*                      p_type = POINTER ; */
9934     }
9935
9936     /* now that we have the pointer type we assign
9937     the pointer values */
9938     switch (p_type) {
9939
9940     case POINTER:       
9941     case IPOINTER:
9942         genNearPointerGet (left,result,ic);
9943         break;
9944
9945     case PPOINTER:
9946         genPagedPointerGet(left,result,ic);
9947         break;
9948
9949     case FPOINTER:
9950         genFarPointerGet (left,result,ic);
9951         break;
9952
9953     case CPOINTER:
9954         genConstPointerGet (left,result,ic);
9955         //pic16_emitcodePointerGet (left,result,ic);
9956         break;
9957
9958     case GPOINTER:
9959 #if 0
9960       if (IS_PTR_CONST(type))
9961         genConstPointerGet (left,result,ic);
9962       else
9963 #endif
9964         genGenPointerGet (left,result,ic);
9965       break;
9966
9967     default:
9968       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9969               "genPointerGet: illegal pointer type");
9970     
9971     }
9972
9973 }
9974
9975 /*-----------------------------------------------------------------*/
9976 /* genPackBits - generates code for packed bit storage             */
9977 /*-----------------------------------------------------------------*/
9978 static void genPackBits (sym_link    *etype , operand *result,
9979                          operand *right ,
9980                          char *rname, int p_type)
9981 {
9982   int shCnt = 0 ;
9983   int offset = 0  ;
9984   int rLen = 0 ;
9985   int blen, bstr ;   
9986   char *l ;
9987
9988         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9989         blen = SPEC_BLEN(etype);
9990         bstr = SPEC_BSTR(etype);
9991
9992         if(AOP_TYPE(right) == AOP_LIT) {
9993                 if((blen == 1) && (bstr < 8)) {
9994                   unsigned long lit;
9995                         /* it is a single bit, so use the appropriate bit instructions */
9996
9997                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
9998
9999                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10000 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10001                         if((p_type == POINTER) && (result)) {
10002                                 /* workaround to reduce the extra lfsr instruction */
10003                                 if(lit) {
10004                                         pic16_emitpcode(POC_BSF,
10005                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
10006                                 } else {
10007                                         pic16_emitpcode(POC_BCF,
10008                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
10009                                 }
10010                         } else {
10011
10012                                 if(lit) {
10013                                         pic16_emitpcode(POC_BSF,
10014                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10015                                 } else {
10016                                         pic16_emitpcode(POC_BCF,
10017                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10018                                 }
10019                         }
10020         
10021                   return;
10022                 }
10023
10024                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
10025                 offset++;
10026         } else
10027                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
10028
10029         /* if the bit lenth is less than or    */
10030         /* it exactly fits a byte then         */
10031         if((shCnt=SPEC_BSTR(etype))
10032                 || SPEC_BLEN(etype) <= 8 )  {
10033
10034                 /* shift left acc */
10035                 AccLsh(shCnt);
10036
10037                 /* using PRODL as a temporary register here */
10038                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
10039
10040                 switch (p_type) {
10041                         case FPOINTER:
10042                         case POINTER:
10043                         case GPOINTER:
10044                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10045 //                              pic16_emitcode ("mov","b,a");
10046 //                              pic16_emitcode("mov","a,@%s",rname);
10047                                 break;
10048                 }
10049 #if 1
10050                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10051                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
10052                                         (unsigned char)(0xff >> (8-bstr))) ));
10053                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
10054                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10055 #endif
10056
10057           return;
10058         }
10059
10060
10061         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10062         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10063         exit(-1);
10064
10065
10066     /* if we r done */
10067     if ( SPEC_BLEN(etype) <= 8 )
10068         return ;
10069
10070     pic16_emitcode("inc","%s",rname);
10071     rLen = SPEC_BLEN(etype) ;     
10072
10073
10074
10075     /* now generate for lengths greater than one byte */
10076     while (1) {
10077
10078         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
10079
10080         rLen -= 8 ;
10081         if (rLen <= 0 )
10082             break ;
10083
10084         switch (p_type) {
10085             case POINTER:
10086                 if (*l == '@') {
10087                     MOVA(l);
10088                     pic16_emitcode("mov","@%s,a",rname);
10089                 } else
10090                     pic16_emitcode("mov","@%s,%s",rname,l);
10091                 break;
10092
10093             case FPOINTER:
10094                 MOVA(l);
10095                 pic16_emitcode("movx","@dptr,a");
10096                 break;
10097
10098             case GPOINTER:
10099                 MOVA(l);
10100                 DEBUGpic16_emitcode(";lcall","__gptrput");
10101                 break;  
10102         }   
10103         pic16_emitcode ("inc","%s",rname);
10104     }
10105
10106     MOVA(l);
10107
10108     /* last last was not complete */
10109     if (rLen)   {
10110         /* save the byte & read byte */
10111         switch (p_type) {
10112             case POINTER:
10113                 pic16_emitcode ("mov","b,a");
10114                 pic16_emitcode("mov","a,@%s",rname);
10115                 break;
10116
10117             case FPOINTER:
10118                 pic16_emitcode ("mov","b,a");
10119                 pic16_emitcode("movx","a,@dptr");
10120                 break;
10121
10122             case GPOINTER:
10123                 pic16_emitcode ("push","b");
10124                 pic16_emitcode ("push","acc");
10125                 pic16_emitcode ("lcall","__gptrget");
10126                 pic16_emitcode ("pop","b");
10127                 break;
10128         }
10129
10130         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
10131         pic16_emitcode ("orl","a,b");
10132     }
10133
10134     if (p_type == GPOINTER)
10135         pic16_emitcode("pop","b");
10136
10137     switch (p_type) {
10138
10139     case POINTER:
10140         pic16_emitcode("mov","@%s,a",rname);
10141         break;
10142         
10143     case FPOINTER:
10144         pic16_emitcode("movx","@dptr,a");
10145         break;
10146         
10147     case GPOINTER:
10148         DEBUGpic16_emitcode(";lcall","__gptrput");
10149         break;                  
10150     }
10151 }
10152 /*-----------------------------------------------------------------*/
10153 /* genDataPointerSet - remat pointer to data space                 */
10154 /*-----------------------------------------------------------------*/
10155 static void genDataPointerSet(operand *right,
10156                               operand *result,
10157                               iCode *ic)
10158 {
10159     int size, offset = 0, resoffset=0 ;
10160
10161     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10162     pic16_aopOp(right,ic,FALSE);
10163
10164     size = AOP_SIZE(right);
10165
10166 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10167
10168 #if 0
10169     if ( AOP_TYPE(result) == AOP_PCODE) {
10170       fprintf(stderr,"genDataPointerSet   %s, %d\n",
10171               AOP(result)->aopu.pcop->name,
10172                 (AOP(result)->aopu.pcop->type == PO_DIR)?
10173               PCOR(AOP(result)->aopu.pcop)->instance:
10174               PCOI(AOP(result)->aopu.pcop)->offset);
10175     }
10176 #endif
10177
10178         if(AOP(result)->aopu.pcop->type == PO_DIR)
10179                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
10180
10181         while (size--) {
10182                 if (AOP_TYPE(right) == AOP_LIT) {
10183                   unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
10184
10185                         lit = lit >> (8*offset);
10186                         if(lit&0xff) {
10187                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
10188                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
10189                         } else {
10190                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
10191                         }
10192                 } else {
10193                         mov2w(AOP(right), offset);
10194                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
10195                 }
10196                 offset++;
10197                 resoffset++;
10198         }
10199
10200     pic16_freeAsmop(right,NULL,ic,TRUE);
10201 }
10202
10203
10204
10205 /*-----------------------------------------------------------------*/
10206 /* genNearPointerSet - pic16_emitcode for near pointer put         */
10207 /*-----------------------------------------------------------------*/
10208 static void genNearPointerSet (operand *right,
10209                                operand *result, 
10210                                iCode *ic)
10211 {
10212   asmop *aop = NULL;
10213   char *l;
10214   sym_link *retype;
10215   sym_link *ptype = operandType(result);
10216   sym_link *resetype;
10217     
10218         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10219         retype= getSpec(operandType(right));
10220         resetype = getSpec(operandType(result));
10221   
10222         pic16_aopOp(result,ic,FALSE);
10223     
10224         /* if the result is rematerializable &
10225          * in data space & not a bit variable */
10226         
10227         /* and result is not a bit variable */
10228         if (AOP_TYPE(result) == AOP_PCODE
10229 //              && AOP_TYPE(result) == AOP_IMMD
10230                 && DCL_TYPE(ptype) == POINTER
10231                 && !IS_BITFIELD(retype)
10232                 && !IS_BITFIELD(resetype)) {
10233
10234                 genDataPointerSet (right,result,ic);
10235                 pic16_freeAsmop(result,NULL,ic,TRUE);
10236           return;
10237         }
10238
10239         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10240         pic16_aopOp(right,ic,FALSE);
10241         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10242
10243         /* if the value is already in a pointer register
10244          * then don't need anything more */
10245         if (!AOP_INPREG(AOP(result))) {
10246                 /* otherwise get a free pointer register */
10247                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10248
10249                 if( (AOP_TYPE(result) == AOP_PCODE) 
10250                         && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10251                                 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10252                 {
10253                   if(!IS_BITFIELD(resetype))
10254                         pic16_loadFSR0( result );  // patch 10
10255                 } else {
10256                         // set up FSR0 with address of result
10257                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10258                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10259                 }
10260
10261         }
10262 //      else
10263 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10264
10265         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10266
10267         /* if bitfield then unpack the bits */
10268         if (IS_BITFIELD(resetype)) {
10269                 genPackBits (resetype, result, right, NULL, POINTER);
10270         } else {
10271                 /* we have can just get the values */
10272           int size = AOP_SIZE(right);
10273           int offset = 0 ;    
10274
10275                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10276                 while (size--) {
10277                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10278                         if (*l == '@' ) {
10279                                 //MOVA(l);
10280                                 //pic16_emitcode("mov","@%s,a",rname);
10281                                 pic16_emitcode("movf","indf0,w ;1");
10282                         } else {
10283
10284                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
10285                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
10286                                         if (size) {                                                                     // 
10287                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
10288                                         } else {                                                                        // 
10289                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
10290                                         }                                                                               // 
10291                                 } else { // no literal                                                                  // 
10292                                         if(size) {                                                                      // 
10293                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10294                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10295                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
10296                                         } else {                                                                        // 
10297                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10298                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10299                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
10300                                         }                                                                               //
10301                                 }                                                                                       // patch 10
10302                         }
10303                         offset++;
10304                 }
10305         }
10306
10307         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10308         /* now some housekeeping stuff */
10309         if (aop) {
10310                 /* we had to allocate for this iCode */
10311                 pic16_freeAsmop(NULL,aop,ic,TRUE);
10312         } else { 
10313                 /* we did not allocate which means left
10314                  * already in a pointer register, then
10315                  * if size > 0 && this could be used again
10316                  * we have to point it back to where it 
10317                  * belongs */
10318                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10319                 if (AOP_SIZE(right) > 1
10320                         && !OP_SYMBOL(result)->remat
10321                         && ( OP_SYMBOL(result)->liveTo > ic->seq
10322                                 || ic->depth )) {
10323
10324                   int size = AOP_SIZE(right) - 1;
10325
10326                         while (size--)
10327                                 pic16_emitcode("decf","fsr0,f");
10328                         //pic16_emitcode("dec","%s",rname);
10329                 }
10330         }
10331
10332         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10333         /* done */
10334 //release:
10335         pic16_freeAsmop(right,NULL,ic,TRUE);
10336         pic16_freeAsmop(result,NULL,ic,TRUE);
10337 }
10338
10339 /*-----------------------------------------------------------------*/
10340 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
10341 /*-----------------------------------------------------------------*/
10342 static void genPagedPointerSet (operand *right,
10343                                operand *result, 
10344                                iCode *ic)
10345 {
10346     asmop *aop = NULL;
10347     regs *preg = NULL ;
10348     char *rname , *l;
10349     sym_link *retype;
10350        
10351     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10352
10353     retype= getSpec(operandType(right));
10354     
10355     pic16_aopOp(result,ic,FALSE);
10356     
10357     /* if the value is already in a pointer register
10358        then don't need anything more */
10359     if (!AOP_INPREG(AOP(result))) {
10360         /* otherwise get a free pointer register */
10361         aop = newAsmop(0);
10362         preg = getFreePtr(ic,&aop,FALSE);
10363         pic16_emitcode("mov","%s,%s",
10364                 preg->name,
10365                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10366         rname = preg->name ;
10367     } else
10368         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10369     
10370     pic16_freeAsmop(result,NULL,ic,TRUE);
10371     pic16_aopOp (right,ic,FALSE);
10372
10373     /* if bitfield then unpack the bits */
10374     if (IS_BITFIELD(retype)) 
10375         genPackBits (retype,result,right,rname,PPOINTER);
10376     else {
10377         /* we have can just get the values */
10378         int size = AOP_SIZE(right);
10379         int offset = 0 ;        
10380         
10381         while (size--) {
10382             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10383             
10384             MOVA(l);
10385             pic16_emitcode("movx","@%s,a",rname);
10386
10387             if (size)
10388                 pic16_emitcode("inc","%s",rname);
10389
10390             offset++;
10391         }
10392     }
10393     
10394     /* now some housekeeping stuff */
10395     if (aop) {
10396         /* we had to allocate for this iCode */
10397         pic16_freeAsmop(NULL,aop,ic,TRUE);
10398     } else { 
10399         /* we did not allocate which means left
10400            already in a pointer register, then
10401            if size > 0 && this could be used again
10402            we have to point it back to where it 
10403            belongs */
10404         if (AOP_SIZE(right) > 1 &&
10405             !OP_SYMBOL(result)->remat &&
10406             ( OP_SYMBOL(result)->liveTo > ic->seq ||
10407               ic->depth )) {
10408             int size = AOP_SIZE(right) - 1;
10409             while (size--)
10410                 pic16_emitcode("dec","%s",rname);
10411         }
10412     }
10413
10414     /* done */
10415     pic16_freeAsmop(right,NULL,ic,TRUE);
10416     
10417         
10418 }
10419
10420 /*-----------------------------------------------------------------*/
10421 /* genFarPointerSet - set value from far space                     */
10422 /*-----------------------------------------------------------------*/
10423 static void genFarPointerSet (operand *right,
10424                               operand *result, iCode *ic)
10425 {
10426     int size, offset ;
10427     sym_link *retype = getSpec(operandType(right));
10428
10429     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10430     pic16_aopOp(result,ic,FALSE);
10431
10432     /* if the operand is already in dptr 
10433     then we do nothing else we move the value to dptr */
10434     if (AOP_TYPE(result) != AOP_STR) {
10435         /* if this is remateriazable */
10436         if (AOP_TYPE(result) == AOP_IMMD)
10437             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10438         else { /* we need to get it byte by byte */
10439             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10440             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10441             if (options.model == MODEL_FLAT24)
10442             {
10443                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10444             }
10445         }
10446     }
10447     /* so dptr know contains the address */
10448     pic16_freeAsmop(result,NULL,ic,TRUE);
10449     pic16_aopOp(right,ic,FALSE);
10450
10451     /* if bit then unpack */
10452     if (IS_BITFIELD(retype)) 
10453         genPackBits(retype,result,right,"dptr",FPOINTER);
10454     else {
10455         size = AOP_SIZE(right);
10456         offset = 0 ;
10457
10458         while (size--) {
10459             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10460             MOVA(l);
10461             pic16_emitcode("movx","@dptr,a");
10462             if (size)
10463                 pic16_emitcode("inc","dptr");
10464         }
10465     }
10466
10467     pic16_freeAsmop(right,NULL,ic,TRUE);
10468 }
10469
10470 /*-----------------------------------------------------------------*/
10471 /* genGenPointerSet - set value from generic pointer space         */
10472 /*-----------------------------------------------------------------*/
10473 static void genGenPointerSet (operand *right,
10474                               operand *result, iCode *ic)
10475 {
10476         int i, size, offset, lit;
10477         sym_link *retype = getSpec(operandType(right));
10478
10479         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10480
10481         pic16_aopOp(result,ic,FALSE);
10482         pic16_aopOp(right,ic,FALSE);
10483         size = AOP_SIZE(right);
10484         offset = 0;
10485
10486         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10487
10488         /* if the operand is already in dptr 
10489                 then we do nothing else we move the value to dptr */
10490         if (AOP_TYPE(result) != AOP_STR) {
10491                 /* if this is remateriazable */
10492                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10493                 // WARNING: anythig until "else" is untested!
10494                 if (AOP_TYPE(result) == AOP_IMMD) {
10495                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10496                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10497                         // load FSR0 from immediate
10498                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10499                         offset = 0;
10500                         while(size--) {
10501                                 if(size) {
10502                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10503                                 } else {
10504                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10505                                 }
10506                                 offset++;
10507                         }
10508                         goto release;
10509                 }
10510                 else { /* we need to get it byte by byte */
10511                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10512                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10513
10514                         // set up FSR0 with address of result
10515                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10516                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10517
10518                         /* hack hack! see if this the FSR. If so don't load W */
10519                         if(AOP_TYPE(right) != AOP_ACC) {
10520
10521                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10522
10523                                 if(AOP_TYPE(right) == AOP_LIT)
10524                                 {
10525                                         // copy literal
10526                                         // note: pic16_popGet handles sign extension
10527                                         for(i=0;i<size;i++) {
10528                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10529                                                 if(i < size-1)
10530                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10531                                                 else
10532                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10533                                         }
10534                                 } else {
10535                                         // copy regs
10536
10537                                         for(i=0;i<size;i++) {
10538                                                 if(i < size-1)
10539                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10540                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
10541                                                 else
10542                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10543                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
10544                                         }
10545                                 }
10546                                 goto release;
10547                         } 
10548                         // right = ACC
10549                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10550                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10551                         goto release;
10552         } // if (AOP_TYPE(result) != AOP_IMMD)
10553
10554         } // if (AOP_TYPE(result) != AOP_STR)
10555         /* so dptr know contains the address */
10556
10557
10558         /* if bit then unpack */
10559         if (IS_BITFIELD(retype)) 
10560                 genPackBits(retype,result,right,"dptr",GPOINTER);
10561         else {
10562                 size = AOP_SIZE(right);
10563                 offset = 0 ;
10564
10565                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
10566
10567                 // set up FSR0 with address of result
10568                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10569                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10570         
10571                 while (size--) {
10572                         if (AOP_TYPE(right) == AOP_LIT) {
10573                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10574                                 if (size) {
10575                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10576                                 } else {
10577                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10578                                 }
10579                         } else { // no literal
10580                                 if(size) {
10581                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10582                                 } else {
10583                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10584                                 }
10585                         }
10586                         offset++;
10587                 }
10588         }
10589
10590         release:
10591         pic16_freeAsmop(right,NULL,ic,TRUE);
10592         pic16_freeAsmop(result,NULL,ic,TRUE);
10593 }
10594
10595 /*-----------------------------------------------------------------*/
10596 /* genPointerSet - stores the value into a pointer location        */
10597 /*-----------------------------------------------------------------*/
10598 static void genPointerSet (iCode *ic)
10599 {    
10600     operand *right, *result ;
10601     sym_link *type, *etype;
10602     int p_type;
10603
10604     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10605
10606     right = IC_RIGHT(ic);
10607     result = IC_RESULT(ic) ;
10608
10609     /* depending on the type of pointer we need to
10610     move it to the correct pointer register */
10611     type = operandType(result);
10612     etype = getSpec(type);
10613     /* if left is of type of pointer then it is simple */
10614     if (IS_PTR(type) && !IS_FUNC(type->next)) {
10615         p_type = DCL_TYPE(type);
10616     }
10617     else {
10618         /* we have to go by the storage class */
10619         p_type = PTR_TYPE(SPEC_OCLS(etype));
10620
10621 /*      if (SPEC_OCLS(etype)->codesp ) { */
10622 /*          p_type = CPOINTER ;  */
10623 /*      } */
10624 /*      else */
10625 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10626 /*              p_type = FPOINTER ; */
10627 /*          else */
10628 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10629 /*                  p_type = PPOINTER ; */
10630 /*              else */
10631 /*                  if (SPEC_OCLS(etype) == idata ) */
10632 /*                      p_type = IPOINTER ; */
10633 /*                  else */
10634 /*                      p_type = POINTER ; */
10635     }
10636
10637     /* now that we have the pointer type we assign
10638     the pointer values */
10639     switch (p_type) {
10640
10641     case POINTER:
10642     case IPOINTER:
10643         genNearPointerSet (right,result,ic);
10644         break;
10645
10646     case PPOINTER:
10647         genPagedPointerSet (right,result,ic);
10648         break;
10649
10650     case FPOINTER:
10651         genFarPointerSet (right,result,ic);
10652         break;
10653
10654     case GPOINTER:
10655         genGenPointerSet (right,result,ic);
10656         break;
10657
10658     default:
10659       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10660               "genPointerSet: illegal pointer type");
10661     }
10662 }
10663
10664 /*-----------------------------------------------------------------*/
10665 /* genIfx - generate code for Ifx statement                        */
10666 /*-----------------------------------------------------------------*/
10667 static void genIfx (iCode *ic, iCode *popIc)
10668 {
10669   operand *cond = IC_COND(ic);
10670   int isbit =0;
10671
10672   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10673
10674   pic16_aopOp(cond,ic,FALSE);
10675
10676   /* get the value into acc */
10677   if (AOP_TYPE(cond) != AOP_CRY)
10678     pic16_toBoolean(cond);
10679   else
10680     isbit = 1;
10681   /* the result is now in the accumulator */
10682   pic16_freeAsmop(cond,NULL,ic,TRUE);
10683
10684   /* if there was something to be popped then do it */
10685   if (popIc)
10686     genIpop(popIc);
10687
10688   /* if the condition is  a bit variable */
10689   if (isbit && IS_ITEMP(cond) && 
10690       SPIL_LOC(cond)) {
10691     genIfxJump(ic,SPIL_LOC(cond)->rname);
10692     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10693   }
10694   else {
10695     if (isbit && !IS_ITEMP(cond))
10696       genIfxJump(ic,OP_SYMBOL(cond)->rname);
10697     else
10698       genIfxJump(ic,"a");
10699   }
10700   ic->generated = 1;
10701
10702 }
10703
10704 /*-----------------------------------------------------------------*/
10705 /* genAddrOf - generates code for address of                       */
10706 /*-----------------------------------------------------------------*/
10707 static void genAddrOf (iCode *ic)
10708 {
10709   operand *result, *left;
10710   int size;
10711   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
10712   pCodeOp *pcop0, *pcop1, *pcop2;
10713
10714         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10715
10716         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10717         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10718
10719         sym = OP_SYMBOL( left );
10720
10721         size = AOP_SIZE(IC_RESULT(ic));
10722
10723
10724         if(sym->onStack) {
10725                 DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
10726         
10727                 return;
10728         }
10729         
10730 //      if(pic16_debug_verbose) {
10731 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10732 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10733 //      }
10734         
10735         /* Assume that what we want the address of is in data space
10736          * since there is no stack on the PIC, yet! -- VR */
10737         /* low */
10738         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10739
10740         /* high */
10741         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10742         
10743         /* upper */
10744         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10745         
10746
10747         if (size == 3) {
10748                 pic16_emitpcode(POC_MOVLW, pcop0);
10749                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10750                 pic16_emitpcode(POC_MOVLW, pcop1);
10751                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10752                 pic16_emitpcode(POC_MOVLW, pcop2);
10753                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10754         } else
10755         if (size == 2) {
10756                 pic16_emitpcode(POC_MOVLW, pcop0);
10757                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10758                 pic16_emitpcode(POC_MOVLW, pcop1);
10759                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10760         } else {
10761                 pic16_emitpcode(POC_MOVLW, pcop0);
10762                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10763         }
10764
10765         pic16_freeAsmop(result,NULL,ic,TRUE);
10766         pic16_freeAsmop(left, NULL, ic, FALSE);
10767 }
10768
10769
10770 #if 0
10771 /*-----------------------------------------------------------------*/
10772 /* genFarFarAssign - assignment when both are in far space         */
10773 /*-----------------------------------------------------------------*/
10774 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10775 {
10776     int size = AOP_SIZE(right);
10777     int offset = 0;
10778     char *l ;
10779     /* first push the right side on to the stack */
10780     while (size--) {
10781         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10782         MOVA(l);
10783         pic16_emitcode ("push","acc");
10784     }
10785     
10786     pic16_freeAsmop(right,NULL,ic,FALSE);
10787     /* now assign DPTR to result */
10788     pic16_aopOp(result,ic,FALSE);
10789     size = AOP_SIZE(result);
10790     while (size--) {
10791         pic16_emitcode ("pop","acc");
10792         pic16_aopPut(AOP(result),"a",--offset);
10793     }
10794     pic16_freeAsmop(result,NULL,ic,FALSE);
10795         
10796 }
10797 #endif
10798
10799 /*-----------------------------------------------------------------*/
10800 /* genAssign - generate code for assignment                        */
10801 /*-----------------------------------------------------------------*/
10802 static void genAssign (iCode *ic)
10803 {
10804   operand *result, *right;
10805   int size, offset,know_W;
10806   unsigned long lit = 0L;
10807
10808   result = IC_RESULT(ic);
10809   right  = IC_RIGHT(ic) ;
10810
10811   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10812   
10813   /* if they are the same */
10814   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10815     return ;
10816
10817   pic16_aopOp(right,ic,FALSE);
10818   pic16_aopOp(result,ic,TRUE);
10819
10820   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10821
10822   /* if they are the same registers */
10823   if (pic16_sameRegs(AOP(right),AOP(result)))
10824     goto release;
10825
10826   /* if the result is a bit */
10827   if (AOP_TYPE(result) == AOP_CRY) {
10828     /* if the right size is a literal then
10829        we know what the value is */
10830     if (AOP_TYPE(right) == AOP_LIT) {
10831           
10832       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10833                   pic16_popGet(AOP(result),0));
10834
10835       if (((int) operandLitValue(right))) 
10836         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10837                        AOP(result)->aopu.aop_dir,
10838                        AOP(result)->aopu.aop_dir);
10839       else
10840         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10841                        AOP(result)->aopu.aop_dir,
10842                        AOP(result)->aopu.aop_dir);
10843       goto release;
10844     }
10845
10846     /* the right is also a bit variable */
10847     if (AOP_TYPE(right) == AOP_CRY) {
10848       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10849       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10850       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10851
10852       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10853                      AOP(result)->aopu.aop_dir,
10854                      AOP(result)->aopu.aop_dir);
10855       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10856                      AOP(right)->aopu.aop_dir,
10857                      AOP(right)->aopu.aop_dir);
10858       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10859                      AOP(result)->aopu.aop_dir,
10860                      AOP(result)->aopu.aop_dir);
10861       goto release ;
10862     }
10863
10864     /* we need to or */
10865     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10866     pic16_toBoolean(right);
10867     emitSKPZ;
10868     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10869     //pic16_aopPut(AOP(result),"a",0);
10870     goto release ;
10871   }
10872
10873   /* bit variables done */
10874   /* general case */
10875   size = AOP_SIZE(result);
10876   offset = 0 ;
10877
10878   if(AOP_TYPE(right) == AOP_LIT) {
10879         if(!IS_FLOAT(operandType( right )))
10880                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10881         else {
10882            union {
10883               unsigned long lit_int;
10884               float lit_float;
10885             } info;
10886         
10887                 /* take care if literal is a float */
10888                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
10889                 lit = info.lit_int;
10890         }
10891   }
10892
10893 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
10894 //                      sizeof(unsigned long int), sizeof(float));
10895
10896   if(AOP_TYPE(right) != AOP_LIT
10897         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
10898         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
10899         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
10900
10901         // set up table pointer
10902         if( (AOP_TYPE(right) == AOP_PCODE)
10903                 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
10904                 || (AOP(right)->aopu.pcop->type == PO_DIR)))
10905         {
10906                 fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
10907                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
10908                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10909                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
10910                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10911                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
10912                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10913         } else {
10914                 fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
10915                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
10916                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
10917                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
10918                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
10919                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
10920                                 pic16_popCopyReg(&pic16_pc_tblptru)));
10921         }
10922
10923         size = min(AOP_SIZE(right), AOP_SIZE(result));
10924         while(size--) {
10925                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10926                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
10927                         pic16_popGet(AOP(result),offset)));
10928                 offset++;
10929         }
10930
10931         if(AOP_SIZE(result) > AOP_SIZE(right)) {
10932                 size = AOP_SIZE(result) - AOP_SIZE(right);
10933                 while(size--) {
10934                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
10935                         offset++;
10936                 }
10937         }
10938         goto release;
10939   }
10940
10941
10942
10943 #if 0
10944 /* VR - What is this?! */
10945   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10946     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10947     if(aopIdx(AOP(result),0) == 4) {
10948
10949       /* this is a workaround to save value of right into wreg too,
10950        * value of wreg is going to be used later */
10951       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10952       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10953       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10954       goto release;
10955     } else
10956 //      assert(0);
10957       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10958   }
10959 #endif
10960
10961   know_W=-1;
10962   while (size--) {
10963   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10964     if(AOP_TYPE(right) == AOP_LIT) {
10965       if(lit&0xff) {
10966         if(know_W != (lit&0xff))
10967           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10968         know_W = lit&0xff;
10969         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10970       } else
10971         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10972
10973       lit >>= 8;
10974
10975     } else if (AOP_TYPE(right) == AOP_CRY) {
10976       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10977       if(offset == 0) {
10978         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10979         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10980       }
10981     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10982         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10983         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10984     } else {
10985   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10986
10987 #if 1
10988         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10989            normally should work, but mind that the W register live range
10990            is not checked, so if the code generator assumes that the W
10991            is already loaded after such a pair, wrong code will be generated.
10992            
10993            Checking the live range is the next step.
10994            This is experimental code yet and has not been fully tested yet.
10995            USE WITH CARE. Revert to old code by setting 0 to the condition above.
10996            Vangelis Rokas 030603 (vrokas@otenet.gr) */
10997            
10998         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10999 #else   
11000         /* This is the old code, which is assumed(?!) that works fine(!?) */
11001
11002         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11003         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11004 #endif
11005     }
11006             
11007     offset++;
11008   }
11009
11010     
11011  release:
11012   pic16_freeAsmop (right,NULL,ic,FALSE);
11013   pic16_freeAsmop (result,NULL,ic,TRUE);
11014 }   
11015
11016 /*-----------------------------------------------------------------*/
11017 /* genJumpTab - generates code for jump table                       */
11018 /*-----------------------------------------------------------------*/
11019 static void genJumpTab (iCode *ic)
11020 {
11021     symbol *jtab;
11022     char *l;
11023
11024     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11025
11026     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
11027     /* get the condition into accumulator */
11028     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
11029     MOVA(l);
11030     /* multiply by three */
11031     pic16_emitcode("add","a,acc");
11032     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
11033
11034     jtab = newiTempLabel(NULL);
11035     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
11036     pic16_emitcode("jmp","@a+dptr");
11037     pic16_emitcode("","%05d_DS_:",jtab->key+100);
11038
11039     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
11040     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
11041     emitSKPNC;
11042     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
11043     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
11044     pic16_emitpLabel(jtab->key);
11045
11046     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
11047
11048     /* now generate the jump labels */
11049     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
11050          jtab = setNextItem(IC_JTLABELS(ic))) {
11051         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
11052         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
11053         
11054     }
11055
11056 }
11057
11058 /*-----------------------------------------------------------------*/
11059 /* genMixedOperation - gen code for operators between mixed types  */
11060 /*-----------------------------------------------------------------*/
11061 /*
11062   TSD - Written for the PIC port - but this unfortunately is buggy.
11063   This routine is good in that it is able to efficiently promote 
11064   types to different (larger) sizes. Unfortunately, the temporary
11065   variables that are optimized out by this routine are sometimes
11066   used in other places. So until I know how to really parse the 
11067   iCode tree, I'm going to not be using this routine :(.
11068 */
11069 static int genMixedOperation (iCode *ic)
11070 {
11071 #if 0
11072   operand *result = IC_RESULT(ic);
11073   sym_link *ctype = operandType(IC_LEFT(ic));
11074   operand *right = IC_RIGHT(ic);
11075   int ret = 0;
11076   int big,small;
11077   int offset;
11078
11079   iCode *nextic;
11080   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
11081
11082   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11083
11084   nextic = ic->next;
11085   if(!nextic)
11086     return 0;
11087
11088   nextright = IC_RIGHT(nextic);
11089   nextleft  = IC_LEFT(nextic);
11090   nextresult = IC_RESULT(nextic);
11091
11092   pic16_aopOp(right,ic,FALSE);
11093   pic16_aopOp(result,ic,FALSE);
11094   pic16_aopOp(nextright,  nextic, FALSE);
11095   pic16_aopOp(nextleft,   nextic, FALSE);
11096   pic16_aopOp(nextresult, nextic, FALSE);
11097
11098   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
11099
11100     operand *t = right;
11101     right = nextright;
11102     nextright = t; 
11103
11104     pic16_emitcode(";remove right +","");
11105
11106   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
11107 /*
11108     operand *t = right;
11109     right = nextleft;
11110     nextleft = t; 
11111 */
11112     pic16_emitcode(";remove left +","");
11113   } else
11114     return 0;
11115
11116   big = AOP_SIZE(nextleft);
11117   small = AOP_SIZE(nextright);
11118
11119   switch(nextic->op) {
11120
11121   case '+':
11122     pic16_emitcode(";optimize a +","");
11123     /* if unsigned or not an integral type */
11124     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
11125       pic16_emitcode(";add a bit to something","");
11126     } else {
11127
11128       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
11129
11130       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
11131         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
11132         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
11133       } else
11134         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
11135
11136       offset = 0;
11137       while(--big) {
11138
11139         offset++;
11140
11141         if(--small) {
11142           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11143             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11144             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11145           }
11146
11147           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11148           emitSKPNC;
11149           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11150                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
11151                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
11152           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11153           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
11154
11155         } else {
11156           pic16_emitcode("rlf","known_zero,w");
11157
11158           /*
11159             if right is signed
11160               btfsc  right,7
11161                addlw ff
11162           */
11163           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11164             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11165             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11166           } else {
11167             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11168           }
11169         }
11170       }
11171       ret = 1;
11172     }
11173   }
11174   ret = 1;
11175
11176 release:
11177   pic16_freeAsmop(right,NULL,ic,TRUE);
11178   pic16_freeAsmop(result,NULL,ic,TRUE);
11179   pic16_freeAsmop(nextright,NULL,ic,TRUE);
11180   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
11181   if(ret)
11182     nextic->generated = 1;
11183
11184   return ret;
11185 #else
11186   return 0;
11187 #endif
11188 }
11189 /*-----------------------------------------------------------------*/
11190 /* genCast - gen code for casting                                  */
11191 /*-----------------------------------------------------------------*/
11192 static void genCast (iCode *ic)
11193 {
11194   operand *result = IC_RESULT(ic);
11195   sym_link *ctype = operandType(IC_LEFT(ic));
11196   sym_link *rtype = operandType(IC_RIGHT(ic));
11197   operand *right = IC_RIGHT(ic);
11198   int size, offset ;
11199
11200         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11201         /* if they are equivalent then do nothing */
11202         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
11203                 return ;
11204
11205         pic16_aopOp(right,ic,FALSE) ;
11206         pic16_aopOp(result,ic,FALSE);
11207
11208         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11209
11210         /* if the result is a bit */
11211         if (AOP_TYPE(result) == AOP_CRY) {
11212         
11213                 /* if the right size is a literal then
11214                  * we know what the value is */
11215                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11216
11217                 if (AOP_TYPE(right) == AOP_LIT) {
11218                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
11219                                 pic16_popGet(AOP(result),0));
11220
11221                         if (((int) operandLitValue(right))) 
11222                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
11223                                         AOP(result)->aopu.aop_dir,
11224                                         AOP(result)->aopu.aop_dir);
11225                         else
11226                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
11227                                         AOP(result)->aopu.aop_dir,
11228                                         AOP(result)->aopu.aop_dir);
11229                         goto release;
11230                 }
11231
11232                 /* the right is also a bit variable */
11233                 if (AOP_TYPE(right) == AOP_CRY) {
11234                         emitCLRC;
11235                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
11236
11237                         pic16_emitcode("clrc","");
11238                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11239                                 AOP(right)->aopu.aop_dir,
11240                                 AOP(right)->aopu.aop_dir);
11241                         pic16_aopPut(AOP(result),"c",0);
11242                         goto release ;
11243                 }
11244
11245                 /* we need to or */
11246                 if (AOP_TYPE(right) == AOP_REG) {
11247                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
11248                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
11249                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
11250                 }
11251                 pic16_toBoolean(right);
11252                 pic16_aopPut(AOP(result),"a",0);
11253                 goto release ;
11254         }
11255
11256         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
11257           int offset = 1;
11258
11259                 size = AOP_SIZE(result);
11260
11261                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11262
11263                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
11264                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
11265                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
11266
11267                 while (size--)
11268                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11269
11270                 goto release;
11271         }
11272
11273         /* if they are the same size : or less */
11274         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
11275
11276                 /* if they are in the same place */
11277                 if (pic16_sameRegs(AOP(right),AOP(result)))
11278                         goto release;
11279
11280                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11281 #if 0
11282                 if (IS_PTR_CONST(rtype))
11283 #else
11284                 if (IS_CODEPTR(rtype))
11285 #endif
11286                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
11287
11288 #if 0
11289                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
11290 #else
11291                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
11292 #endif
11293                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
11294
11295 #if 0
11296                 if(AOP_TYPE(right) == AOP_IMMD) {
11297                   pCodeOp *pcop0, *pcop1, *pcop2;
11298                   symbol *sym = OP_SYMBOL( right );
11299
11300                         size = AOP_SIZE(result);
11301                         /* low */
11302                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11303                         /* high */
11304                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11305                         /* upper */
11306                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11307         
11308                         if (size == 3) {
11309                                 pic16_emitpcode(POC_MOVLW, pcop0);
11310                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11311                                 pic16_emitpcode(POC_MOVLW, pcop1);
11312                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11313                                 pic16_emitpcode(POC_MOVLW, pcop2);
11314                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11315                         } else
11316                         if (size == 2) {
11317                                 pic16_emitpcode(POC_MOVLW, pcop0);
11318                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11319                                 pic16_emitpcode(POC_MOVLW, pcop1);
11320                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11321                         } else {
11322                                 pic16_emitpcode(POC_MOVLW, pcop0);
11323                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11324                         }
11325                 } else
11326 #endif
11327                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11328                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
11329                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11330                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
11331                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11332                         if(AOP_SIZE(result) <2)
11333                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
11334                 } else {
11335                         /* if they in different places then copy */
11336                         size = AOP_SIZE(result);
11337                         offset = 0 ;
11338                         while (size--) {
11339                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11340                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11341                                 offset++;
11342                         }
11343                 }
11344                 goto release;
11345         }
11346
11347         /* if the result is of type pointer */
11348         if (IS_PTR(ctype)) {
11349           int p_type;
11350           sym_link *type = operandType(right);
11351           sym_link *etype = getSpec(type);
11352
11353                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
11354
11355                 /* pointer to generic pointer */
11356                 if (IS_GENPTR(ctype)) {
11357                   char *l = zero;
11358             
11359                         if (IS_PTR(type)) 
11360                                 p_type = DCL_TYPE(type);
11361                         else {
11362                 /* we have to go by the storage class */
11363                 p_type = PTR_TYPE(SPEC_OCLS(etype));
11364
11365 /*              if (SPEC_OCLS(etype)->codesp )  */
11366 /*                  p_type = CPOINTER ;  */
11367 /*              else */
11368 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11369 /*                      p_type = FPOINTER ; */
11370 /*                  else */
11371 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11372 /*                          p_type = PPOINTER; */
11373 /*                      else */
11374 /*                          if (SPEC_OCLS(etype) == idata ) */
11375 /*                              p_type = IPOINTER ; */
11376 /*                          else */
11377 /*                              p_type = POINTER ; */
11378             }
11379                 
11380             /* the first two bytes are known */
11381       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
11382             size = GPTRSIZE - 1; 
11383             offset = 0 ;
11384             while (size--) {
11385               if(offset < AOP_SIZE(right)) {
11386       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
11387                 if ((AOP_TYPE(right) == AOP_PCODE) && 
11388                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11389                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11390                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11391                 } else { 
11392                   pic16_aopPut(AOP(result),
11393                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11394                          offset);
11395                 }
11396               } else 
11397                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11398               offset++;
11399             }
11400             /* the last byte depending on type */
11401             switch (p_type) {
11402             case IPOINTER:
11403             case POINTER:
11404                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11405                 break;
11406             case FPOINTER:
11407               pic16_emitcode(";BUG!? ","%d",__LINE__);
11408                 l = one;
11409                 break;
11410             case CPOINTER:
11411               pic16_emitcode(";BUG!? ","%d",__LINE__);
11412                 l = "#0x02";
11413                 break;                          
11414             case PPOINTER:
11415               pic16_emitcode(";BUG!? ","%d",__LINE__);
11416                 l = "#0x03";
11417                 break;
11418                 
11419             default:
11420                 /* this should never happen */
11421                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11422                        "got unknown pointer type");
11423                 exit(1);
11424             }
11425             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
11426             goto release ;
11427         }
11428         
11429         /* just copy the pointers */
11430         size = AOP_SIZE(result);
11431         offset = 0 ;
11432         while (size--) {
11433             pic16_aopPut(AOP(result),
11434                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11435                    offset);
11436             offset++;
11437         }
11438         goto release ;
11439     }
11440     
11441
11442
11443     /* so we now know that the size of destination is greater
11444     than the size of the source.
11445     Now, if the next iCode is an operator then we might be
11446     able to optimize the operation without performing a cast.
11447     */
11448     if(genMixedOperation(ic))
11449       goto release;
11450
11451     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11452     
11453     /* we move to result for the size of source */
11454     size = AOP_SIZE(right);
11455     offset = 0 ;
11456     while (size--) {
11457       pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
11458 //      pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
11459 //      pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
11460       offset++;
11461     }
11462
11463     /* now depending on the sign of the destination */
11464     size = AOP_SIZE(result) - AOP_SIZE(right);
11465     /* if unsigned or not an integral type */
11466     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11467       while (size--)
11468         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11469     } else {
11470       /* we need to extend the sign :( */
11471
11472       if(size == 1) {
11473         /* Save one instruction of casting char to int */
11474         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
11475         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11476         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
11477       } else {
11478         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11479
11480         if(offset)
11481           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11482         else
11483           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11484         
11485         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
11486
11487         while (size--)
11488           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
11489       }
11490     }
11491
11492 release:
11493     pic16_freeAsmop(right,NULL,ic,TRUE);
11494     pic16_freeAsmop(result,NULL,ic,TRUE);
11495
11496 }
11497
11498 /*-----------------------------------------------------------------*/
11499 /* genDjnz - generate decrement & jump if not zero instrucion      */
11500 /*-----------------------------------------------------------------*/
11501 static int genDjnz (iCode *ic, iCode *ifx)
11502 {
11503     symbol *lbl, *lbl1;
11504     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11505
11506     if (!ifx)
11507         return 0;
11508     
11509     /* if the if condition has a false label
11510        then we cannot save */
11511     if (IC_FALSE(ifx))
11512         return 0;
11513
11514     /* if the minus is not of the form 
11515        a = a - 1 */
11516     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11517         !IS_OP_LITERAL(IC_RIGHT(ic)))
11518         return 0;
11519
11520     if (operandLitValue(IC_RIGHT(ic)) != 1)
11521         return 0;
11522
11523     /* if the size of this greater than one then no
11524        saving */
11525     if (getSize(operandType(IC_RESULT(ic))) > 1)
11526         return 0;
11527
11528     /* otherwise we can save BIG */
11529     lbl = newiTempLabel(NULL);
11530     lbl1= newiTempLabel(NULL);
11531
11532     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11533     
11534     if (IS_AOP_PREG(IC_RESULT(ic))) {
11535         pic16_emitcode("dec","%s",
11536                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11537         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11538         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11539     } else {    
11540
11541
11542       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11543       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11544
11545       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11546       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
11547
11548     }
11549 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11550 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11551 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11552 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11553
11554     
11555     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11556     ifx->generated = 1;
11557     return 1;
11558 }
11559
11560 /*-----------------------------------------------------------------*/
11561 /* genReceive - generate code for a receive iCode                  */
11562 /*-----------------------------------------------------------------*/
11563 static void genReceive (iCode *ic)
11564 {    
11565         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11566
11567 #if 0
11568         fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
11569                 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
11570 #endif
11571 //      pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
11572
11573         if (isOperandInFarSpace(IC_RESULT(ic)) &&
11574                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11575                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11576
11577           int size = getSize(operandType(IC_RESULT(ic)));
11578           int offset =  pic16_fReturnSizePic - size;
11579
11580                 assert( 0 );
11581                 while (size--) {
11582                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11583                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11584                         offset++;
11585                 }
11586
11587                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
11588
11589                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11590                 size = AOP_SIZE(IC_RESULT(ic));
11591                 offset = 0;
11592                 while (size--) {
11593                         pic16_emitcode ("pop","acc");
11594                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11595                 }
11596         } else {
11597                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
11598
11599                 _G.accInUse++;
11600                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11601                 _G.accInUse--;
11602                 assignResultValue(IC_RESULT(ic), 0);
11603         }
11604
11605         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11606 }
11607
11608 /*-----------------------------------------------------------------*/
11609 /* genDummyRead - generate code for dummy read of volatiles        */
11610 /*-----------------------------------------------------------------*/
11611 static void
11612 genDummyRead (iCode * ic)
11613 {
11614   pic16_emitcode ("; genDummyRead","");
11615   pic16_emitcode ("; not implemented","");
11616
11617   ic = ic;
11618 }
11619
11620 /*-----------------------------------------------------------------*/
11621 /* genpic16Code - generate code for pic16 based controllers        */
11622 /*-----------------------------------------------------------------*/
11623 /*
11624  * At this point, ralloc.c has gone through the iCode and attempted
11625  * to optimize in a way suitable for a PIC. Now we've got to generate
11626  * PIC instructions that correspond to the iCode.
11627  *
11628  * Once the instructions are generated, we'll pass through both the
11629  * peep hole optimizer and the pCode optimizer.
11630  *-----------------------------------------------------------------*/
11631
11632 void genpic16Code (iCode *lic)
11633 {
11634     iCode *ic;
11635     int cln = 0;
11636
11637     lineHead = lineCurr = NULL;
11638
11639     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11640     pic16_addpBlock(pb);
11641
11642 #if 0
11643     /* if debug information required */
11644     if (options.debug && currFunc) {
11645       if (currFunc) {
11646         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11647       }
11648     }
11649 #endif
11650
11651     for (ic = lic ; ic ; ic = ic->next ) {
11652
11653       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11654         if ( cln != ic->lineno ) {
11655             if ( options.debug ) {
11656               debugFile->writeCLine (ic);
11657             }
11658             
11659             if(!options.noCcodeInAsm) {
11660                 pic16_addpCode2pBlock(pb,
11661                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
11662                                 printCLine(ic->filename, ic->lineno)));
11663             }
11664
11665             cln = ic->lineno ;
11666         }
11667         
11668         if(options.iCodeInAsm) {
11669                 char *l;
11670                 /* insert here code to print iCode as comment */
11671                 l = Safe_strdup(printILine(ic));
11672                 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11673         }
11674         
11675         /* if the result is marked as
11676            spilt and rematerializable or code for
11677            this has already been generated then
11678            do nothing */
11679         if (resultRemat(ic) || ic->generated ) 
11680             continue ;
11681         
11682         /* depending on the operation */
11683         switch (ic->op) {
11684         case '!' :
11685             pic16_genNot(ic);
11686             break;
11687             
11688         case '~' :
11689             pic16_genCpl(ic);
11690             break;
11691             
11692         case UNARYMINUS:
11693             genUminus (ic);
11694             break;
11695             
11696         case IPUSH:
11697             genIpush (ic);
11698             break;
11699             
11700         case IPOP:
11701             /* IPOP happens only when trying to restore a 
11702                spilt live range, if there is an ifx statement
11703                following this pop then the if statement might
11704                be using some of the registers being popped which
11705                would destroy the contents of the register so
11706                we need to check for this condition and handle it */
11707             if (ic->next            && 
11708                 ic->next->op == IFX &&
11709                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
11710                 genIfx (ic->next,ic);
11711             else
11712                 genIpop (ic);
11713             break; 
11714             
11715         case CALL:
11716             genCall (ic);
11717             break;
11718             
11719         case PCALL:
11720             genPcall (ic);
11721             break;
11722             
11723         case FUNCTION:
11724             genFunction (ic);
11725             break;
11726             
11727         case ENDFUNCTION:
11728             genEndFunction (ic);
11729             break;
11730             
11731         case RETURN:
11732             genRet (ic);
11733             break;
11734             
11735         case LABEL:
11736             genLabel (ic);
11737             break;
11738             
11739         case GOTO:
11740             genGoto (ic);
11741             break;
11742             
11743         case '+' :
11744             pic16_genPlus (ic) ;
11745             break;
11746             
11747         case '-' :
11748             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11749                 pic16_genMinus (ic);
11750             break;
11751             
11752         case '*' :
11753             genMult (ic);
11754             break;
11755             
11756         case '/' :
11757             genDiv (ic) ;
11758             break;
11759             
11760         case '%' :
11761             genMod (ic);
11762             break;
11763             
11764         case '>' :
11765             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
11766             break;
11767             
11768         case '<' :
11769             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11770             break;
11771             
11772         case LE_OP:
11773         case GE_OP:
11774         case NE_OP:
11775             
11776             /* note these two are xlated by algebraic equivalence
11777                during parsing SDCC.y */
11778             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11779                    "got '>=' or '<=' shouldn't have come here");
11780             break;      
11781             
11782         case EQ_OP:
11783             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11784             break;          
11785             
11786         case AND_OP:
11787             genAndOp (ic);
11788             break;
11789             
11790         case OR_OP:
11791             genOrOp (ic);
11792             break;
11793             
11794         case '^' :
11795             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11796             break;
11797             
11798         case '|' :
11799                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11800             break;
11801             
11802         case BITWISEAND:
11803             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11804             break;
11805             
11806         case INLINEASM:
11807             genInline (ic);
11808             break;
11809             
11810         case RRC:
11811             genRRC (ic);
11812             break;
11813             
11814         case RLC:
11815             genRLC (ic);
11816             break;
11817             
11818         case GETHBIT:
11819             genGetHbit (ic);
11820             break;
11821             
11822         case LEFT_OP:
11823             genLeftShift (ic);
11824             break;
11825             
11826         case RIGHT_OP:
11827             genRightShift (ic);
11828             break;
11829             
11830         case GET_VALUE_AT_ADDRESS:
11831             genPointerGet(ic);
11832             break;
11833             
11834         case '=' :
11835             if (POINTER_SET(ic))
11836                 genPointerSet(ic);
11837             else
11838                 genAssign(ic);
11839             break;
11840             
11841         case IFX:
11842             genIfx (ic,NULL);
11843             break;
11844             
11845         case ADDRESS_OF:
11846             genAddrOf (ic);
11847             break;
11848             
11849         case JUMPTABLE:
11850             genJumpTab (ic);
11851             break;
11852             
11853         case CAST:
11854             genCast (ic);
11855             break;
11856             
11857         case RECEIVE:
11858             genReceive(ic);
11859             break;
11860             
11861         case SEND:
11862             addSet(&_G.sendSet,ic);
11863             break;
11864
11865         case DUMMY_READ_VOLATILE:
11866           genDummyRead (ic);
11867           break;
11868
11869         default :
11870             ic = ic;
11871         }
11872     }
11873
11874
11875     /* now we are ready to call the
11876        peep hole optimizer */
11877     if (!options.nopeep) {
11878       peepHole (&lineHead);
11879     }
11880     /* now do the actual printing */
11881     printLine (lineHead,codeOutFile);
11882
11883 #ifdef PCODE_DEBUG
11884     DFPRINTF((stderr,"printing pBlock\n\n"));
11885     pic16_printpBlock(stdout,pb);
11886 #endif
11887
11888     return;
11889 }
11890